
一、TCP/IP协议数据封装过程TCP首部、IP首部二、TCP 粘包TCP 是面向字节流协议没有消息边界UDP 面向报文不存在粘包粘包产生原因TCP 无消息边界 缓冲区缓存 Nagle 攒包 IP 分片1.TCP 本身特性面向字节流 收发缓冲区TCP 不保留应用层消息边界数据只是一串连续字节内核有发送缓冲区、接收缓冲区数据先放缓冲区不是调用一次 send 就立刻发一个独立包。2.发送方Nagle 算法重点Nagle 会把多次小数据攒起来合并成一个大报文段一起发送减少小包数量提升网络效率 → 多条消息粘在一起(粘包)。3.接收方缓冲区读取接收端内核收到数据放接收缓冲区应用程序 recv 一次读的字节数不确定一次读可能把多条消息一起读出来。4.网络链路IP 分片数据包太大超过 MTU网络层会分片传输一条消息被拆成多片也就是拆包。粘包解决方法1.固定长度每次消息大小固定接收方每次固定读对应长度。缺点浪费流量短消息也要补齐到固定大小。2.特殊分隔符分隔符法消息末尾加特殊标记比如\n、\r\n接收方读到分隔符代表一条消息结束。缺点消息内容里面不能出现这个分隔符否则解析错乱。3.消息头 消息体头部固定字节存放消息体长度比如前 4 字节表示后面数据有多长后面跟着真实消息内容流程先读头部拿到长度 → 再根据长度读取对应字节的消息体。优点灵活、稳定项目最常用。4.关闭 Nagle 算法不推荐单独用来解决粘包setsockopt设置 TCP_NODELAY关闭 Nagle有数据立刻发。注意关闭 Nagle 不能根治粘包只是减少攒包缓冲区依然会带来粘包一般配合上面方案一起使用1.粘包是 TCP字节流特性自带的正常现象TCP 只管可靠传输字节不区分应用消息必须应用层自己做消息边界2.UDP 不会粘包UDP 面向报文一次 sendto 对应一个报文内核保留报文边界3.粘包、拆包本质是同一个问题应用层分不清消息起点终点