Linux——UDP协议和TCP协议

发布时间:2026/10/23 13:21:59
Linux——UDP协议和TCP协议 一、UDP协议1. 协议格式源端端口号对端端口号数据报长度校验和数据字段的功能源端端口对端端口描述了通信两端的进程数据报长度描述包含UDP头部在内的报长度长度2个字节范围0~65535因此UDP报文最大长度64K数据报最大长度64k-8校验和用于校验收到的数据和发送的数据是否一致算法二进制反码求和算法1.填充报文数据将校验和置02.针对报文所有数据逐字节取反相加求和3.得到的值填充到校验和中接收方收到数据之后逐字节反码求和得到的结果是0则表示数据一致2.协议特性无连接不可靠面向数据报无连接通信双方不需要管理对方的状态只需要知道对方的地址就可以发送数据连接本质是通信双方对于对方的状态维护不可靠不保证数据安全有序的到达对方面向数据报有最大长度限制的传输方式64k-8数据传输是一种块式传输比如当发送方要发送数据的时候此时发送方在应用层要发送一个Hello一旦这个Hello到达传输层传输层就会在这个数据前面追加一个UDP报头在这个报头中此时数据报长度保存的值就是13因为头部字段是8个字节Hello是5个字节。这个数据经过网络发送给了对方对方接收到数据之后知道UDP报头是8个字节所以先取出8个字节的报头从这个报头中看数据报长度13知道报头的长度是8个字节所以数据长度就是5接下来就在缓冲区中直接取出5个字节长度的数据。数据报传输的时候报文中明确标识了报文长度接收方接收数据的时候不允许出现半个多个一次性取出的情况3.UDP编程注意事项1.UDP不保证数据安全有序的到达对端因此若需要的话则需要程序员在应用层进行安全管理包序管理2.UDP报文有最大长度限制因此发送数据的时候若数据过大则需程序员在应用层进行分包将大数据分割成多个小段进行发送3.UDP无连接因此支持广播传输通过一次sendto发送数据可以将数据发送给当前局域网网络中所有主机a. UDP 无连接TCP 是面向连接通信前必须先三次握手建立点对点的专属通道只能你和对方两个主机通信不能一次性发给一堆主机。 UDP 不用握手发数据前不需要和接收方建立连接。发包的时候直接在数据包里填好目的地址就往外扔发完就不管了。无连接这个特性是 UDP 能实现广播的前提。b. 广播是什么广播向同一个局域网内的所有主机发送一份数据。 局域网有一个广播地址把 UDP 数据包的目的 IP 设为广播地址交换机就会把这个包转发给本网段里每一台主机。c. sendto 函数UDP 编程用sendto()发送数据而不是 TCP 的send/write。sendto的特点每次发送都要指定本次的目标地址IP 端口。普通单播目标 IP 填某一台单独主机 IP → 只发给这一台广播目标 IP 填局域网广播地址→ 只调用一次sendto生成单个 UDP 数据包网络会自动把这个包投递到局域网全部主机。二、TCP协议1.协议格式16位源端端口16位对端端口32位序号32位确认序号4位头长6位保留6位标志位16位窗口大小16位校验和16位紧急指针选项数据0~40字节数据2. 字段功能116位源端端口对端端口描述通信两端进程2.32位序号实现有序传输的核心字段描述了数据的序号描述了我当前进程的数据从哪个序号开始到哪个序号结束接收方接收到数据之后根据这个序号来进行排序332位的确认序号实现有序传输的核心字段44位头部长度以4字节为单位描述整个TCP头部长度TCP头部长度最小20字节最大是60字节因为正常头部是占20个字节如果有选项数据40个字节就是60个字节TCP报文解析核心字段56位保留字段暂时没有用到66位标志位URG紧急指针有效位-用于表示后边的紧急指针数据是否有效紧急指针本质是一个偏移量指向了一个带外紧急数据位置也就是说TCP里面在我正常传输数据的时候此时我突然有一个优先级更高的数据需要优先传输给对端TCP是支持这个操作的这个紧急指针就是描述紧急数据的结束位置从我们的报头开始到紧急数据结束这之间就是我们一个紧急的优先级数据。ACK确认应答标志-标识当前报文是一个确认应答报文在建立连接的时候置位PSH立即传输标志位-TCP默认有延迟发送机制该标志位用于标识立即发送不要延迟TCP中有一个机制叫做延迟发送机制就是我现在调用一个send接口向对端发送数据这个数据在发送的时候实际上是把数据放到发送缓冲区里面操作系统选择合适的时机将数据发送到对端主机上也就是说数据发送到缓冲区之后并不会被立即进行发送而是有一个延迟时间延迟发送为什么要延迟发送IO缓冲区当我们向文件中写入数据的时候数据并不会被立即写入文件而是先放到缓冲区里面因为每一次写文件都意味着你要操作一次磁盘从内存跟硬盘之间进行一个数据交互网卡中也是同样的道理我们每次发送数据都会涉及到内存跟网卡之间的一个数据交互那么我们的数据每一次数据通过send就直接通过网卡发送出去那么就意味着如果在大量的这种小数据发送的时候就显得我们需要很多次IO操作才能完成我们的数据发送但是IO操作的效率是比较低的他涉及到两个设备之间的一个数据传输所以 大佬们就在磁盘上用了一个缓冲区先把数据给他堆积起来堆积成一个大数据再一次性写入磁盘里面网卡也是同样的道理延迟发送机制是为了减少IO次数来提高IO效率RST重置连接标志位-通知对方当前连接有异常若要通信则重新建立连接SYN建立连接标志位-标识当前报文是一个连接建立请求报文FIN连接断开标志位-标识当前报文是一个连接断开报文用于通知对方我要连接断开了用于通知对方我不再给你发送数据了FIN Finish连接断开标志。当报文头里FIN1代表发送方这边不会再往这个连接里发新数据了通知对方准备关闭连接。重点FIN 只是说「我不再发数据」不等于我立刻不收你的数据。716位窗口大小用于TCP的滑动窗口机制实现流量控制避免发送方发送数据过快而来不及接收导致数据丢包的情况因为缓冲区的大小固定socket的接收缓冲区和发送缓冲区默认情况下是64K那么如果我们的发送方发送数据过快但是接收方接收数据之后要处理它就接收的特别慢那么发送的多了对方的接收缓冲区就容易被塞满他的接收缓冲区一旦被塞满那么后续的数据就没有地方可以放了就出现了数据丢失816位校验和二进制反码求和算法实现校验接收到的数据与发送数据是否一致916位紧急指针存储一个偏移量指向紧急数据的末尾100~40字节选项数据通常用于连接建立时的一些协商数据........3.协议特性面向连接可靠传输面向字节流传输1面向连接通信双方需要维护对方的状态以便于保证数据的传输是有效的有意义的连接管理三次握手建立连接四次挥手断开连接三次握手建立连接过程四次挥手断开连接过程典型面试题1三次握手的过程客户端向服务端发送SYN请求服务端回复ACKSYN客户端回复ACK2 握手为什么是三次为什么不是两次或四次两次是不够安全的当前的SYN有可能是正常的也有可能是延迟到达的无效报文四次是没有的必要的因为每个报文都要传输报头占据带宽3挥手为什么是四次而不是三次FIN包主要是用于表示我不给对方发送数据了并不代表我不接收数据但是不表示对方不再给我发送数据因此对方依然可以继续发送数据给我因此从设计上将两个操作分开了题外话只不过很多时候如果对方也关闭的比较快两个可能会合并到一起发送连接中的状态迁移变化1客户端在向服务端发送SYN连接请求会进入一个状态叫做SYN_SEND表示此时已经给对方发送了连接建立请求等待对方确认回复2服务端在接收SYN之前的状态是LISTEN才会开始处理连接请求3服务端收到这个请求并且确认回复之后会进入一个状态SYN_RCVD 这个状态就是 等待对方给我最后一次确认回复4客户端一旦收到了我们服务端的ACK和SYN之后他就会进入一个状态ESTABLISHED 也就是就绪状态5服务端收到最后一次ACK他也会进入一个状态ESTABLISHED表示就绪 就绪状态才允许进行数据通信也就是说两方的状态进入就绪状态才能进行数据通信4三次握手中超时了双方是如何处理的①客户端发送SYN后等待超时客户端会重新传SYN请求次数限制②服务端发送ACKSYN之后等待超时客户端不对服务端进行确认会怎么样服务端会给客户端回复一个RST报文然后释放socket服务端收到 SYN 后会把这个连接信息放到SYN 半连接队列就是存这些处于SYN_RCVD状态的半连接。 如果大量客户端只发 SYN不回复最后的 ACK就会塞满半连接队列 →SYN 洪水攻击SYN Flood服务端无法处理正常新连接。此时这个问题服务端给客户端回复RST解决不了客户端收到 SYNACK并且发出了 ACK但是 ACK 报文在网络丢包 服务端看不到 ACK依旧走重传逻辑但客户端自己已经进入 ESTABLISHED客户端认为连接好了服务端还在 SYN_RCVD。后续客户端发数据的时候服务端会回复 RST 重置连接。断开中状态迁移变化服务端和客户端都可以进行断开连接主动关闭方给服务端主发送一个FIN包然后此时会进入一个状态FIN_WAIT_1状态-》此时意味着我给对方发送了一个FIN包等待对方确认回复对方收到FIN包之后会给对方确认回复确认回复之后就会进入一个状态CLOSE_WAIT状态-》等待我们的上层关闭连接主动关闭方收到ACK之后 会进入一个状态FIN_WAIT_2状态-》表示我收到了ACK并且等待对方给我发送FIN包的状态对方调用close发送FIN之后会进入一个状态LAST_ACK状态-》等待对方最后一次回复主动关闭方收到FIN包之后给对方进行一个ACK的确认确认之后会进入一个状态TIME_WAIT状态 他会等待2个MSL时间然后进入一个状态叫做CLOSED状态对方收到ACK之后会进入一个状态CLOSE状态5TIME_WAIT状态有什么用主动关闭方收到了对方的FIN包并进行回复之后进入的状态等待两个MSL时间之后进入CLOSED状态释放连接MSL报文最大生命周期因为主动关闭方最后一次ACK有可能会丢失对方收不到ACK超时后就会重传FIN包一旦我们的主动关闭方直接进入CLOSED释放连接就有可能有新的连接使用了相同的地址收到这个重传的FIN包就对新连接造成了影响因此为了避免产生这种情况因此主动关闭方等待两个MSL之后再进入CLOSED释放连接两个MSL的原因一个MSL是等待ACK用一个最大生命周期的时间到达对端的时间但是ACK可能没有到达对端丢失了接下来又用一个MSL重新传输FIN6一台主机上出现了大量的TIME_WAIT连接是什么原因怎么解决TIME_WAIT是主动方才会出现的状态主机上出现了大量的TIME_WAIT 意味着主机上频繁的且大量的在进行主动的连接关闭操作这种情况常见于主机上运行了爬虫程序解决方案1使用setsockop接口进行套接字选项设置开启地址重用复用处于TIME_OUT状态连接地址2进行系统配置设置将TIME_WAIT等待时间调短7一台主机上出现了大量的CLOSE_WAIT是什么原因被动关闭方收到FIN包并进行ACK回复后进入的状态等待上层关闭连接若产生大量的CLOSE_WAIT有可能是代码中漏掉了CLOSE关闭连接操作连接断开了但是没有CLOSEFIN请求一定是一段调用了close(fd)或者调用了shutdown(fd,write)才会向对方发送FIN对端客户端已经发起关闭、内核收到 FIN 并 ack客户端到服务端这个方向的数据流已经断了半断开但服务端应用层没有执行 close () 系统调用所以完整连接无法释放卡在 CLOSE_WAIT半关闭本身不是 bug一直卡在 CLOSE_WAIT 不释放 socket才是 bug。我们拆开讲✅ TCP 半关闭特性客户端发 FIN代表客户端不再发送数据但服务端依然可以继续往客户端发数据。这个机制本身完全正常是 TCP 设计的能力。✅ 什么时候正常服务端业务处理完剩余数据之后调用close()内核发出服务端的 FIN走完四次挥手连接释放。此时 CLOSE_WAIT 只是一个短暂过渡状态一闪而过你几乎看不到。❌ 什么时候变成 BUG 服务端收到客户端 FIN内核 ACK进入 CLOSE_WAIT。但是服务端应用程序一直不去调用 close ()。哪怕服务端已经没有数据要发给客户端了代码也没有 close。 这个 socket 就永久卡在 CLOSE_WAIT不会消失。连接断开在程序中的表现recv取完数据后返回0而不再阻塞send触发异常SIG_PIPE让程序直接退出避免退出忽略或自定义SIGPIPE信号的处理方式TCP的连接保活机制服务端与客户端若长时间7200s没有数据往来则会每隔一段时间75s会给客户端发送一个保洁探测数据包要求客户端进行确认回复若连续多次9都没有收到回复则认为连接断开释放资源这些默认数据可以通过setsockopt套接字选项设置也可以改变系统配置2.可靠传输保证数据安全有序的到达对端核心发送方和接收方如何发现出现了丢包丢包后该如何处理如何尽量避免丢包1.发送方和接收方如何发现出现了丢包1确认应答机制发送方针对发送的每一个字节数据都要求接收方收到之后进行确认回复发送数据后若长时间没有收到回复则认为丢包停等协议发送方收到确认回复之后才会发送下一条数据适用于网络极差的场景原理停等是最简单的可靠传输协议属于 ARQ自动重传请求。发送方发送 1 个分组然后停止发送停下来等待接收方的 ACK 确认帧。接收方收到正确分组 → 返回 ACK 确认。发送方收到 ACK 之后才可以继续发下一个分组。如果超时没收到 ACK发送方认为分组丢了重传当前这个分组。快速重传协议在管线化传输中接收方收到了后边的数据但是没有收到前边的数据则会对前边的数据进行应答发送方若连续三次都收到同一个确认序号的确认报文则会立即从指定的确认序号开始重传数据不再等超时属于 TCP 的差错恢复机制不是独立协议是对超时重传的优化。核心思想不等计时器超时提前重传丢失的报文段。 超时重传要等漫长的超时时间很慢快速重传靠重复 ACK来提前感知丢包。原理规则接收方收到失序报文序号不是期望收到的那个就立即发送重复 ACKACK 仍然确认期望收到的序号。发送方如果连续收到 3 个重复 ACK一共 4 个相同 ACK判定这个报文段丢包立刻重传该报文不用等超时定时器到期。重点3 个冗余 ACKduplicate ACK触发快速重传。举个例子 发送方发送 1、2、3、4 号报文报文 2 丢了报文 3、4 到达接收方接收方收到 3不是想要的 2 → 回复 ACK2重复 ACK#1接收方收到 4不是想要的 2 → 回复 ACK2重复 ACK#2 发送方收到第 3 个 ACK2总共 3 个重复 ACK→直接重传报文 2不等超时。回退n步协议从丢掉的报文开始往后的数据都重传适用于网络一般的场景属于流水线 ARQ 自动重传请求在停等协议基础上改进不用发一个等一个可以连续发送多个分组。核心思想发送方维持发送窗口可以一次性连续发送窗口内的多个报文不用每发一个就停下等 ACK。 接收方只按序接收收到期望序号的报文 → 上交上层返回 ACK收到失序报文直接丢弃不缓存持续发送重复 ACK一旦发现某个报文丢失从丢失的那个报文开始后面所有已经发出去的报文全部重传回退 N 个这就是名字来源。选择重传协议针对丢掉的单个报文进行重传哪个包丢了就重传哪个包适用于网络较好的场景超时重传机制发送方等待超时发现丢包之后就会对原来的数据进行重传这两个机制依赖于协议中的序号和确认序号字段延迟应答机制接收方收到数据之后并不会立即给予确认回复可能会进行一个延迟不用每发接收一条数据之后进行一次ACK延迟回复会从我们接收到的最后一个数据进行ACK确认回复节省一部分的确认回复捎带应答机制接收方收到数据以后如果刚好当前要给对方发送数据会把确认回复和要发送的数据合并到一起进行发送确认回复协议中的确认序号节省确认回复所导致的空报文延时发送数据发送方send将数据放到发送缓冲区之后并不会立即发送数据延迟一点时间就可能会将大量的小数据攒成大数据通过依次IO实现传输2.避免没必要的丢包1滑动窗口机制通过协议中的窗口大小字段告诉接收方最多给自己发送多少数据实现流量控制避免发送方发送数据过多导致接收方缓冲区溢出导致丢包MTU最大传输单元链路层根据物理硬件限制的最大数据帧大小包含报头在内若一个报文他特别大UDP64k-8但是受限于链路层MTU限制在网络层就会被分片割成多个小的数据帧进行传输。TCP在传输的时候三次握手阶段就会协商MSS最大数据段大小MSSMTU-IP报头大小-TCP报头大小1460以太网限制双方会在TCP选项中携带自己所支持的MSS大小选择其中较小的值作为实际的MSS传输大小往后的数据发送的时候都会以该大小进行发送。在进行数据传输的过程中接收方回复ACK之后才会将刚刚发送的数据从发送缓冲区中删除出来接收窗口的滑动接收窗口是接收方用来告诉发送方我现在最多还能接收多少字节的数据。 窗口有两个边界后沿左边界、前沿右边界窗口大小前沿-后沿取决于对方数据中的窗口大小字段接收方通知给发送方的数据必须小于等于接收方缓冲区剩余空间的大小发送方通过窗口控制自己接收数据的位置滑动窗口的移动主要用于描述发送方发送数据的序号描述接收方接受的数据序号窗口大小由接收方返回的报文段里的窗口大小字段决定不是发送方定的。后沿已经确认完毕的最后一个字节序号窗口的左边界前沿后沿 接收窗口大小窗口的右边界在【后沿前沿这个区间内的序号是接收方允许发送方继续发送的数据。后沿的移动当接收到了后沿序号的确认应答后沿收到后沿序号的确认应答 ACK才会向右移动。发送方发数据 → 接收方收到完整数据 → 返回 ACK 确认。当 ACK 确认号等于当前窗口后沿序号后沿向右滑动。✅一句话后沿跟着 ACK 确认号走确认了旧数据后沿才往前挪。前沿的移动响应的窗口大小-后沿前沿 后沿 响应报文里的窗口大小 接收方每次回复 ACK 的时候会带上自己当前剩余接收缓冲区大小窗口值。如果接收方缓冲区空闲变多 → 窗口变大 → 前沿右移如果接收方缓冲区快满了 → 窗口变小 → 前沿左移窗口收缩前沿由接收方每次通告的窗口大小决定。发送窗口的大小一定等于相应数据中的窗口大小字段WIN接收缓冲区剩余空闲空间大小WIN前沿-后沿2拥塞机制发送方本身在本地通过维护一个拥塞窗口变量用于控制当前所能发送的数据量用于控制发送方发送数据量避免因为网络状态不好出现丢包发送方又不断大量重传导致网络更加拥塞的情况核心拥塞窗口描述了当前发送方可以发送多少数据拥塞窗口的增长节奏慢启动快增长指数3、字节流传输以字节为单位进行先进先出的传输方式1TCP的粘包问题场景发送方可能会将多次send的数据当做一条报文进行发送接收方可能会将多条数据当做依次recv交付给应用层原因TCP并不会对数据进行缓冲区进行边界管理解决方案TCP没有在传输层进行数据边界管理程序员可以在应用层进行边界管理1.使用特殊字符数据添加结尾标志容易与数据中的特殊字符产生二义性-对数据中的特殊字符进行转义处理2.使用固定长度传输数据容易造成资源浪费且必须明确最大数据长度3.自制LV通信协议实现边界标记LlengthVvalue使用固定的长度的长度字段描述长度字段接收方先接收指定长度的长度字段根据长度字段的值获取数据struct lv{ unit64_t length; char data[]; };若recv接收数据的时候缓冲区没有数据则会阻塞若send发送数据的时候发送缓冲区中数据满了则会阻塞当连接断开的时候或者对端的写操作关闭recv接收完缓冲区数据后继续recv 则不在阻塞返回0当连接断开的时候或对端关闭了读操作send发送数据就会触发异常SIGPIPE

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询