一、网络协议--UDP
UDP用户数据报协议(User Datagram Protocol):传输层
1.1 CS模型&BS模型
1. B/S模型:(browser/serve,浏览器/服务器)
客户端是通用的客户端(浏览器)
一般只做服务器开发
客户端要加载的数据均来自服务器
2. C/S模型:client/server(客户端/服务端)
客户端是一个专用的客户端
服务器和客户端都需开发
客户端可保存资源,本地加载,无需所有数据都请求服务
1.2 套接字相关概念
套接字(Socket)是网络编程的核心接口,用于在不同设备(或同一设备的不同进程)之间建立网络连接并实现数据传输,本质是操作系统提供的"网络通信端点"。
1.3 UDP编程流程
1.3.1UDP客服端/服务端编程流程图

1.3.2 相关函数接口
1.创建通信套接字:socket()
功能:创建一个用于网络通信的套接字,返回套接字文件描述符
函数原型:
cs#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol);
参数:
domain:网络层使用什么协议族
AF_INET:IPv4
AF_INET6:IPv6
type:规定传输层的协议
SOCK_DGRAM : UDP协议
SOCK_STREAM:TCP协议
SOCK_RAW :原始套接字
protocol :0 按照默认协议方式创建
返回值:
成功:套接字文件描述符
失败:-1
2. 绑定地址端口:bind()
功能:绑定自己的IP地址和端口号
函数原型:
csint bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
sockfd:套接字
addr:需要绑定的地址
addrlen:地址大小
返回值:
成功:0
失败:-1
3. 发送数据:sendto()
功能:向指定的目标地址(服务端/客户端)发送UDP数据报。
函数原型:
csssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
参数:
sockfd:套接字
buf: 要发送的数据的首地址
len:要发送的字节数
flags: 0:按照默认方式发送
dest_addr:接收方的地址信息(IP+端口号)
addrlen:接收方地址的大小
返回值:
成功:实际发送的字节数
失败:-1
struct sockaddr_in {sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
网络字节序和主机字节序的概念
网络字节序是通信网络中统一规定的字节顺序,固定为大端(高位字节存低字节,低位字节存高位);
主机字节序是计算机CPU存储数据的字节顺序,分大端和小端(取决于硬件架构,如X86和ARM是小端)
0x1234
小端:0x34
0x12
大端:
0x12
0x34
为什么需要转换?
若直接将主机字节序的数据发送到网络,接收方会解析错误。
关键转换函数
所有函数均定义在<arpa/inet.h>头文件中,核心是4个"h/n"开头的函数(h = hostz主机,
n = network网络,s = short16位, = long32位)
uint32_t htonl(uint32_t hostlong); 主机转网络
uint16_t htons(uint16_t hostshort); 主机转网络
uint32_t ntohl(uint32_t netlong); 网络转主机
uint16_t ntohs(uint16_t netshort); 网络转主机
in_addr_t inet_addr(const char *cp);
功能:
将字符串IP地址转换成二进制IP地址形式
char *inet_ntoa(struct in_addr in);
功能:
将二进制ip转换成字符串
4.接收数据:recvfrom()
功能:从套接字上接收数据
函数原型:
csssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
参数:
sockfd:套接字
buf:存放接收数据的内存首地址
len:希望接收的字节数
flags:0 :按照默认方式接收(阻塞)
src_addr:发送方的地址信息
addrlen:发送发地址的指针
功能:
成功:实际接收到的字节数
1.4 UDP特点
UDP是一种无连接、不可靠、面向数据报 的传输层协议。
1.无需建立连接:通信前无需建立连接(如 TCP 的三次握手),发送方直接向目标地址和端口发送数据报,接收方也无需提前"准备接收"。
-
尽最大努力交付,不安全、不可靠(数据丢包、乱序)
-
面向数据报
-
可实现一对一、一对多的传输
-
机制简单,资源开销小,数据实时性高(VNC、直播)
如何避免UDP丢包?
1.发送方以较慢的速度发送数据,让接收方又足够的时间处理数据。
- 模仿TCP的机制:应答机制
1.5 抓包工具
wireshark
网络抓包:抓取通过设备网卡的网络数据,从而调试和分析网络程序。
使用:
1.sudo wireshark启动抓包工具
-
选取要抓取的网卡---》any
-
选择一个过滤条件
-
开始抓取
-
进行一次网络通信
1.6 UDP报文头部
UDP头部:包含4个字段,总共8字节
UDP头部按"大端序(网络字节序)"存储,字段从左到右(高位到低位)依次为:
|--------|-----|--------------------------------------|
| 字段名称 | 字节数 | 核心作用 |
| 源端口号 | 2 | 发送方网络进程端口号 |
| 目标端口号 | 2 | 接收方网络进程端口号 |
| UDP长度 | 2 | 整个UDP数据报的总长度(8字节头部+数据部分),最大值为65535字节 |
| UDP校验和 | 2 | 数据差错检验 |
二、网络协议------TCP
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接、可靠、基于字节流的传输层通信协议。
2.1 TCP的特点
面向数据流;
有连接(通信之前必须建立连接);
安全可靠的传输机制
4.机制复杂,网络资源开销大
- 本质只能实现一对一的通信(使用 TCP 并发方式可实现一对多通信)
2.2 TCP三次握手和四次挥手机制
TCP三次挥手:TCP建立连接时,需要进行三次握手,为了确保收发双方通信之前都已准备就绪。

TCP四次挥手:TCP断开连接时,需要进行四次挥手,确保断开连接前双方都以通信结束。

2.3 TCP的编程流程
2.3.1

2.3.2 相关函数接口
服务端专属:绑定与监听
- bind()
2.listen():开启监听
功能:监听建立三次握手的客服端
函数原型:
csint listen(int sockfd, int backlog);
参数:
sockfd:监听套接字
backlog:最大允许监听的客服端个数
返回值:
成功:0
失败:-1
3. 建立连接:accep(服务端)与connect(客服端)
TCP是面向连接的协议,需要通过这两个函数完成"三次握手"的核心流程。
1. connect():客户端发起连接
功能:请求与服务端建立连接
函数原型:
csint connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
sockfd:套接字
addr:要连接的服务器的地址信息
addrlen:服务器地址大小
返回值:
成功:0
失败:-1
1.accept():服务端接收连接
功能:接收建立三次握手的客户端,并产生一个通讯套接字
函数原型:
csint accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);
参数:
socket:监听套接字
address:客户端的地址信息
address_len:客户端地址长的指针
返回值:
成功:通讯套接字
失败:-1
-
数据传输:send()&recv()
-
send():发送数据
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
功能:发送网络数据
参数:
sockfd:网络套接字
buf:要发送的数据首地址
len:发送的字节数
flags:0 :按照默认方式发送
返回值:
成功:实际发送的字节数
失败:-1
- recv():接收数据
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
功能:从网络套接字上接收数据
参数:
sockfd:通讯套接字
buf:存放接收数据的首地址
len:期望接收到的字节数
flag : 0:默认方式接收(阻塞)
返回值:
成功:实际接收到的字节数
失败:-1
对方断开连接:0
2.4 TCP粘包问题
TCP粘包问题:发送方应用层发送的多包数据,将来在接收方可能一次读到,多包数据产生粘连。
产生原因:
1.发送方速度较快,TCP地层可能对多包数据进行重新组帧;
2.接收方数据处理速度较慢,导致多包数据在接收缓冲区缓存,应用层读时,一次将多包数据读出
解决粘包问题的常用方法
1.调整发送速率
2.发送指定大小,将来接收方也接收指定大小
- 应用层为发送的数据增加分隔符,利用分隔符解析
4.封装自定义数据帧进行发送(协议),严格根据协议进行解析
AA C0 00 00 00 F0 00 BB 10 A0 00 00 00 10 校验 BB AA C0 00 00 00 F0 00 BB 10 A0 00 00 00 10 校验 BB AA C0 00 00 00 F0 00 BB 10 A0 00 00 00 10 校验 BB
帧头:AA
帧尾:BB
有效数据长度:C0
有效数据:00 00 00 F0 00 BB 10 A0 00 00 00 10
校验:
8位和校验
16位和校验
CRC校验
三、TCP的其他机制

TCP头部的标志位:
SYN:请求建立连接标志位
ACK:响应报文标志位
PSH:携带数据标志位,通知接收方该从缓冲区读数据
FIN:请求断开连接标志位
RST:复位标志位
URG:紧急数据标志位
机制:
安全可靠:
-
三次握手和四次挥手机制
-
应答机制:
-
超时重传机制:当数据发送出去等待指定时间没有收到响应,此时认为这包数据丢失则进行重传;
-
滑动窗口机制:一段缓冲区,缓存TCP已发送为收到响应,准备发送数据
提高效率:
-
延迟应答机制:发送数据的同时可以等待应答
-
流量控制机制:结合TCP头部的窗口大小,动态调整发送速率。
-
捎带应答机制:ACK报文可能和应用层的数据同时发送
四、UDP&TCP比较
TCP是面向连接、可靠的协议
UDP是无连接、不可靠的协议
具体以一下几个维度对比:
**连接方式:**TCP需要通过"三次握手"建立连接,通信结束后通过"四次挥手"关闭连接,是面向连接的;UDP无需建立连接,直接发送数据,是无连接的;
可靠性:TCP通过确认应答、重传机制、流量控制、拥塞控制等确保数据准确、有序到达,不丢失、不重复;UDP不提供可靠保障,数据发送后无法确认是否到达,可能丢失、乱序;
**传输速率:**TCP慢;UDP快
**数据顺序:**TCP有序;UDP可能乱序