粘包是反常现象 TCP 为什么
一、TCP 粘包现象
TCP 粘包是指发送方发送了若干数据包,然而抵达接纳方之后,数据包的内容所有 “粘连” 在了一同,每个数据包的数据开头间接和下个数据包的数据连在了一同,无法反常辨别。
上方的图片展现了一个 TCP 粘包现象,反常的 3 个数据包由于粘包,被连在了一同,看起来像是一个数据包,结果就很感人了 ...
二、TCP 粘包/拆包 要素
TCP 驳回 “异步” 模式发送运行数据,也就是说,当运行程序中调用Send(packet)发送数据时,只管 Send 函数会立刻前往,然而数据并不必定曾经抵达通讯对方了。运行数据详细什么时刻发,由运行层上方的传输层 TCP 说了算,TCP 经常使用了 3 个重要机制 (确认与重传、滑动窗口流量控制、拥塞控制) 来成功牢靠性传输,保障运行数据的牢靠传输和运行层数据发送顺序和抵达顺序分歧的语义保障。
上方来开展说一下或许造成 粘包/拆包 疑问的要素。
1. 面向字节流的上班个性
TCP 作为传输层,并不了解 (也不关心) 运行层数据的高低文含意,它只会依据通讯双方商定的MSS[1]对发送缓冲区的数据包启动拆分。
所以在运行层的视角来看,一个完整的数据包 (或许是一段聊天文字、一个图片、一个视频) 或许会教训不同的发送环节:
2. 缓冲机制
TCP 在发送数据时,会将数据放入发送缓冲区;在接纳数据时,会将数据放入接纳缓冲区。TCP 会尽或许地将发送缓冲区中的数据打包成一个或多个数据包发送进来,而接纳方在读取数据时,也会尽量将接纳缓冲区中的数据所有读取进去。这种机制或许造成发送方一次性发送的多个数据包被接纳方一次性性读取,从而引发粘包疑问。
为了尽或许优化发送数据和接受处置数据的功能,作为发送方来讲:
作为接纳方来讲:
3. Nagle 算法
Nagle 算法原理: 发送方曾经发送数据还未被接纳方确认之前,时期假设又有小数据生成,先把小数据搜集起来,凑满一个 MSS (最大报文段大小) 或许收到接纳方 Ack 后再一同发送。经过将小数据包积攒成较大的数据包后再发送,从而提高网络效率。
很显然,依据 Nagle 算法的上班机制,在频繁发送小的数据包时 (例如 Telnet, SSH 终端),会发生粘包现象。
上方是在 Go 言语中封锁 TCP Nagle 算法的示例代码。
package mainfunc main() {conn, _ := net.Dial("tcp", "dbwu.tech:443")fd := conn.(*net.TCPConn).File()// 封锁 Nagle 算法syscall.SetsockoptInt(int(fd.Fd()), syscall.IPPROTO_TCP, syscall.TCP_NODELAY, 1)}
❓ 单纯封锁 Nagle 算法并不能处置粘包疑问,读者思索一下为什么?