UDP报文结构
UDP报头定长8字节,包含源端口目的端口,UDP报文总长和UDP校验和
UDP特点
UDP特点
UDP的特点是无连接和不可靠,它和TCP不一样,TCP的传输需要建立连接,而UDP不需要,而且TCP传输有可靠性UDP不可靠。
UDP的不可靠体现在没有重传机制,也没有确认机制,如果没有成功发送,UDP也不会返回应用层信息。
UDP的传输面向数据报,所以应用层每次的recvfrom和sendto的次数都是一一对应的。而且每次发送接收的都是完整的报文。应用层交给UDP无论多长的报文,UDP都不会拆分和合并发送,而是原封不动发送。
UDP缓冲区
UDP没有真正意义的发送缓存区,因为UDP不需要保障可靠性,不需要重传,也就不需要缓冲区对数据进行存储。
UDP报文大小
UDP首部字段有一个16位报文长度,也就确定了UDP最大长度就是64K,如果应用层发送数据大,就需要在应用层手动分包,分别发送,在对端应用层进行合并。
基于UDP的应用层协议
• NFS:网络文件系统(Network File System)
• TFTP:简单文件传输协议(Trivial File Transfer Protocol)
• DHCP:动态主机配置协议(Dynamic Host Configuration Protocol)
• BOOTP:启动协议(Bootstrap Protocol,用于无盘设备启动)
• DNS:域名系统(Domain Name System)
TCP报文结构
TCP全程传输控制协议,保证对数据的传输控制,TCP面向字节流,有接收缓存区,同时有很多保障可靠性的机制
TCP报头字段包含源端口号目的端口号,32位序列号,32位确认序列号,4位首部长度,6位保留字段,16位窗口大小,16位紧急指针和40字节选项。
TCP大小
由于4位首部长度范围0000-1111只能确定0-15大小,所以首部长度需要乘上4KB大小,所以TCP报头大小范围是0-60,又因为报头大小最小20KB,所以报头大小范围是20-60KB。
6位标志位
URG:标识紧急指针的有效性。
ACK:确认号是否有效
PSH:提示应用层尽快从接收缓存区读取数据
SYN:请求建立连接,把携带SYN标识的称为同步报文段
FIN:通知对方本段关闭连接,携带FIN的叫结束报文段
16位校验和
发送端进行数据填充并附加CRC校验码。接收端若校验失败,则判定数据存在异常。此处的校验范围不仅涵盖TCP首部,同时包含TCP数据部分。
16位紧急指针
紧急指针是当URG有效时,标识紧急数据位置的偏移量,紧急数据大小是1字节,紧急数据会被上层提前处理
TCP确认应答机制
TCP每次发送到对端的数据都会收到一个ACK用来表示对方接受到了数据,同时携带ACK的也是一个报文,但这个报文没有携带数据,所以ACK应答不需要确认,也就是ACK应答不需要新的ACK应答确认应答收到了。
TCP为了效率考虑,没有把每个发送的报文都每次确认,而是一次性发送多个报文后,对端发送一个ACK。但是对方收到的数据未必是有序的,但数据报文需要排列。所以每个报头的序列号和确认序列号就有了作用。例如:客户端发送1000条报文,那最后一条报文序列号是1000,服务器收到后发送确认ACK,这个ACK确认序列号就是1001,代表0-1000的报文都收到了,你下一次报文从我的确认序列号1001发送。
我们会发现,0-1000未必真的全部收到了,而是收到了1000后就说0-1000的报文全部收到,没错,TCP允许少量的报文丢失,当他收到ACK就认为报文发送成功了。
TCP超时重传机制
TCP的丢包分为两种,一种是真的丢包了,还有一种是ACK丢了,无论哪种,都需要进行重传,这样接收端可能会收到很多重复的报文,这时报文序列号又有作用了,它可以让接收端知道自己已经接受了哪些报文了,如果遇到重复的就直接丢弃。
超时重传时间的规定
因为网络环境的堵塞程度不同,重传时间也应该有对应的变化。
• 理想情况下,我们需要确定一个最小时间阈值,确保确认应答必定能在该时限内返回。
• 然而,这个时间阈值会因网络环境差异而有所不同。
• 若超时设置过长,会降低整体重传效率; • 若设置过短,则可能导致数据包重复发送。
为确保TCP在各种网络环境下都能高效通信,系统会动态计算最佳超时时间。
• 在Linux系统(BSD Unix和Windows同样适用)中,超时控制以500ms为基本单位,每次超时重传的时间都是500ms的整数倍。
• 首次重传未获应答时,等待时间将延长至2×500ms后再次重传。 • 若仍未收到应答,则等待时间按4×500ms递增,以此类推,呈指数级增长。
• 当重传次数达到上限时,TCP会判定网络或对端主机异常,强制终止连接。
TCP连接机制
一般情况TCP建立连接三次握手,关闭连接四次挥手
像ACK+SYN类似同时拥有确认应答和报文数据的叫做携带应答。
服务端状态转换:
• [CLOSED → LISTEN] 服务器调用listen后进入LISTEN状态,开始监听客户端连接请求
• [LISTEN → SYN_RCVD] 收到客户端的SYN报文后,将该连接加入内核等待队列,并向客户端发送SYN+ACK确认报文
• [SYN_RCVD → ESTABLISHED] 收到客户端的ACK确认后,连接建立完成,进入可读写状态
• [ESTABLISHED → CLOSE_WAIT] 收到客户端的FIN报文后,发送ACK确认并进入CLOSE_WAIT状态
• [CLOSE_WAIT → LAST_ACK] 处理完待发送数据后,发送FIN报文并进入LAST_ACK状态,等待最终ACK确认
• [LAST_ACK → CLOSED] 收到对FIN的ACK确认后,完全关闭连接
客户端状态转换:
• [CLOSED → SYN_SENT] 调用connect后发送SYN报文,进入连接发起状态
• [SYN_SENT → ESTABLISHED] 收到服务器的SYN+ACK并回复ACK后,连接建立完成
• [ESTABLISHED → FIN_WAIT_1] 调用close后发送FIN报文,进入主动关闭第一阶段
• [FIN_WAIT_1 → FIN_WAIT_2] 收到服务器对FIN的ACK确认后,等待服务器FIN报文
• [FIN_WAIT_2 → TIME_WAIT] 收到服务器的FIN报文后发送ACK,进入等待状态
• [TIME_WAIT → CLOSED] 经过2MSL等待时间后,完全关闭连接