4-10:TCP协议之面向字节流和粘包问题

Posted 快乐江湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4-10:TCP协议之面向字节流和粘包问题相关的知识,希望对你有一定的参考价值。

一:面向字节流

经过前面的叙述,现在我们对TCP面向字节流的理解就更加深刻了。

创建一个TCP的socket,就会在内核中创建一个发送缓冲区和一个接受缓冲区。主要有以下这么几点:

  • 调用write接口,数据会先写入发送缓冲区
  • 如果发送的字节数太长,会被拆分成多个TCP的数据包发出
  • 如果发送的字节数太短,会在缓冲区内等待,等待缓冲区长度差不多了,或者在其他合适的时机将其发送出去
  • 接受数据的时候,数据也是从网卡驱动程序到达内核的接受缓冲区的
  • 应用层可以调用read从接受缓冲区中拿取数据

TCP的一个连接,既有发送缓冲区也有接受缓冲区,所以对于这一个连接,既可以读取数据也可以写入数据——全双工

二:粘包(应用层数据包)问题

TCP协议中是没有同UDP一样的“报文长度”的字段,因此站在应用层角度来看,看到的只是一串连续的字节数,因此应用程序就无法分清数据的界限,有可能会产生粘包问题。

如果避免呢?关键就在于:应用层的协议应该要明确两个包的边界

  • 对于定长的包,保证每次都按固定大小读取即可。例如Request,那么就从缓冲区从头开始按照sizeof(Request)大小依次读取即可
  • 对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位置(比如HTTP协议中conten-length);同时还可以在包与包之前使用特殊的分隔符(比如HTTP协议中的空行

三:TCP异常情况

我们都知道运行中的程序会由于各种各样的原因崩溃,对于非网络程序来说并没有什么大的问题,不过对于网络应用程序由于它还涉及连接问题,所以它不能简单单的拍屁股走人

所以在客户端应用程序崩溃或死亡时,接收端会认为连接还在,一旦接收端有写入操作,接收端发现连接不在了,就会进行reset。即使没有写入操作,TCP自己也会内置一个保活定时器即使询问对方是否还在,如果不在就会释放连接。最经典的就是QQ了。

以上是关于4-10:TCP协议之面向字节流和粘包问题的主要内容,如果未能解决你的问题,请参考以下文章

unity探索者之socket传输protobuf字节流

如何理解是 TCP 面向字节流协议?

TCP-缓冲区和粘包、拆包有啥关系?

Linux:TCP粘包问题的模拟实现以及解决方法

Linux:TCP粘包问题的模拟实现以及解决方法

TCP传输面向字节流如何处理重传呢?