|----------------------------------------------|
| 学习主题:UDP 协议通信模型、Socket 核心 API、Wireshark 抓包实操 |
前言
今天系统学习了传输层当中的 UDP 协议。UDP 是 User Datagram Protocol(用户数据报协议),属于无连接协议;同时梳理了两种主流网络通信架构 B/S 与 C/S,记录 UDP 通信整套系统调用接口以及 Linux 下 Wireshark 抓包工具的使用流程。
一、两种网络通信架构对比
B/S 架构(Browser / Server,浏览器‑服务器架构)
特点
- 使用通用浏览器作为客户端,不需要单独开发客户端程序
- 业务数据资源基本保存在服务端
- 只需要开发维护服务端
C/S 架构(Client / Server,客户端‑服务器架构)
特点
- 使用专用客户端程序
- 客户端、服务端两端都可以保存数据资源
- 客户端和服务端都需要独立开发
|-----|---------|-------------|--------|
| 架构 | 客户端 | 数据存放位置 | 开发工作量 |
| B/S | 通用浏览器 | 主要保存在服务端 | 只开发服务端 |
| C/S | 定制专用客户端 | 客户端、服务端均可存放 | 两端都要开发 |
二、UDP 通信整体流程
UDP 是无连接通信,客户端和服务端调用接口存在明显区别。
|-----------------------------------------------------------------------------|
|
|
|-------------------------------------------------------------------|
| 重点区分:UDP 客户端不需要 bind 绑定端口 ;UDP 服务端必须调用 bind 绑定端口,客户端才能定位到服务端。 |
三、UDP 核心 API 详解
1.socket()
函数原型
|-----------------------------------------------------|
| c int socket(int domain , int type , int protocol); |
功能:创建通信套接字
参数说明
- domain:协议族;AF_INET 代表 IPv4,AF_INET6 代表 IPv6
- type:传输层协议类型;SOCK_STREAM 对应 TCP,SOCK_DGRAM 对应 UDP
- protocol:协议编号,写 0 表示使用默认协议
返回值:成功返回文件描述符(套接字编号);失败返回‑1
2.sendto ()(UDP 发送专用接口)
函数原型
|------------------------------------------------------------------------------------------------------------------------------|
| c ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); |
功能:发送 UDP 报文
参数说明
- sockfd:套接字文件描述符
- buf:待发送数据首地址
- len:待发送数据字节长度
- flags:标志位,填 0 代表默认方式发送
- dest_addr:目标地址信息(IP + 端口)
- addrlen:地址结构体长度
返回值:成功返回实际发送的字节数;失败返回‑1
3.bind()
函数原型
|--------------------------------------------------------------------------|
| c int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); |
功能:将套接字和本机 IP 地址、端口号进行绑定(UDP 服务端专属)
参数说明
- sockfd:套接字编号
- addr:要绑定的地址信息结构体
- addrlen:地址结构体长度
返回值:成功返回 0;失败返回‑1
4.recvfrom ()(UDP 接收专用接口)
函数原型
|---------------------------------------------------------------------------------------------------------------------|
| c ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); |
功能:接收 UDP 报文,同时可以拿到发送方的 IP 与端口信息
参数说明
- sockfd:套接字编号
- buf:缓冲区首地址,用来存放收到的数据
- len:期望接收的最大字节数
- flags:标志位,填 0 代表默认方式接收
- src_addr:输出参数,保存发送方地址信息
- addrlen:地址长度的指针
返回值:成功返回实际收到的字节数;失败返回‑1;收到长度 0 代表对方发送了空数据包
5.IP 地址转换函数
|-------------------------------------------------------------------------------------------------------------------------------------------|
| c //字符串IP转成32位整型IP,例如"192.168.1.10" -> 二进制整型 in_addr_t inet_addr(const char *cp); //32位整型IP转回字符串IP char *inet_ntoa(struct in_addr in); |
6. 地址结构体
|-----------------------------------------------------------------------------------------------------------------------------------|
| c struct sockaddr_in{ sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; }; struct in_addr{ uint32_t s_addr; }; |
四、UDP 协议的特点
- 无连接:通信双方不需要提前建立连接,直接发送数据包
- 面向数据报:数据以完整报文为单位一次性发送
- 尽最大努力交付:UDP 是不安全、不可靠协议,传输过程中可能丢包、乱序
- 协议机制简单,实时性好,传输效率高;适合直播、游戏画面推送等场景
五、Wireshark 网络抓包工具实操
Wireshark 是一款网络抓包工具,可以抓取流经网卡的数据包,用于排查网络故障,分析报文内容。
Linux 下安装命令
|-------------------------------------|
| bash sudo apt-get install wireshark |
UDP 抓包实操流程
- 在终端启动抓包软件:sudo wireshark
- 选择要抓取数据包的网卡,一般直接选择any,抓取全部网卡流量
- 在过滤器栏填写过滤规则,例如udp.port == 50000,只抓取 50000 端口的 UDP 报文
- 运行自己编写的 UDP 客户端、服务端程序进行通信,即可抓取数据包分析
六、今日小结
今天掌握了 UDP 整套通信流程,记住 UDP 和 TCP 最大区别就是无连接、不可靠、面向报文;UDP 服务端必须 bind 端口,客户端不需要 bind;UDP 收发不能使用普通 send、recv,要用 sendto、recvfrom。Wireshark 可以根据端口过滤 UDP 报文,是调试网络程序非常重要的工具。
|---------------------------------------------------------------|
| 后续计划:基于今天笔记完成 UDP 客户端、服务端完整可运行代码,并且使用 Wireshark 抓取自己程序发出的数据包。 |