目录
面向字节流
粘包问题
解决粘包问题的方法
个人主页:东洛的克莱斯韦克-CSDN博客
面向字节流
TCP是一种面向字节流的协议,这意味着TCP并不将传输的数据视为独立的消息或报文,而是将其视为一个连续的字节序列。在TCP连接中,发送方将应用层数据写入TCP发送缓冲区,TCP将这些数据视为字节流进行处理,并在接收方将其重新组合成原始数据。这种处理方式提供了很高的灵活性,因为TCP可以传输任意类型的数据,包括文本、图像、音频等。
创建一个 TCP 的 socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区; 调用 write 时, 数据会先写入发送缓冲区中; 如果发送的字节数太长, 会被拆分成多个 TCP 的数据包发出; 如果发送的字节数太短, 就会先在缓冲区里等待, 等到缓冲区长度差不多了, 或 者其他合适的时机发送出去; 接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区; 然后应用程序可以调用 read 从接收缓冲区拿数据; 另一方面, TCP 的一个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这一 个连接, 既可以读数据, 也可以写数据. 这个概念叫做 全双工 由于缓冲区的存在, TCP 程序的读和写不需要一一匹配, 例如: 写 100 个字节数据时, 可以调用一次 write 写 100 个字节, 也可以调用 100 次 write, 每次写一个字节; 读 100 个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次 read 100 个字节, 也可以一次 read
然而,面向字节流的特性也带来了一些挑战。由于TCP不保留消息的边界,接收方在接收数据时可能无法直接识别出单个消息的起始和结束位置。这可能导致接收方在解析数据时遇到困难,尤其是在发送方发送了多个小消息且这些消息在传输过程中被合并成一个大的数据包时。
粘包问题
粘包问题是指在TCP通信过程中,发送方发送的多个数据包在接收方被错误地合并成一个数据包,导致接收方无法正确地解析出单个的数据包。粘包问题的发生原因主要有以下几点:
TCP的面向字节流特性:如前所述,TCP不保留消息的边界,这是粘包问题发生的根本原因。
发送方发送的数据包较小且发送速率较快:在这种情况下,TCP可能会为了提高传输效率而将多个小数据包合并成一个大的数据包进行发送。
接收方缓冲区大小不足:如果接收方的缓冲区不足以存储所有接收到的数据包,就可能导致数据包在缓冲区中被合并。
网络延迟和丢包:TCP协议虽然是一种可靠的传输协议,但网络延迟和丢包仍然可能导致数据包的到达顺序和时间发生变化,从而增加粘包问题的可能性。
解决粘包问题的方法
为了解决TCP通信中的粘包问题,可以采取以下几种方法:
固定长度的消息:将每个消息的长度固定为某个特定的值。接收方在接收到足够长度的数据后,就认为已经接收到了一个完整的消息。然而,这种方法可能会导致数据的浪费和灵活性降低。
特殊字符作为边界:在消息的末尾添加一个特定的分隔符(如换行符\n)。接收方在接收到这个分隔符时,就认为已经接收到了一个完整的消息。但需要注意的是,如果消息内容中可能包含这个分隔符,则需要进行转义处理。
自定义消息结构:在每个消息前添加一个包含消息长度的头部。接收方在接收到头部后,先解析出消息的长度,然后根据这个长度来读取后续的数据。这种方法既灵活又高效,但需要发送方和接收方事先约定好消息结构的格式。