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协议之面向字节流和粘包问题的主要内容,如果未能解决你的问题,请参考以下文章