TCP协议面试热点(面向字节流,粘包问题,TCP异常情况)

Posted 两片空白

tags:

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

面向字节流

        TCP在内核有自己的接收和发送缓冲区。

        面向字节流最重要的就是接收和发送缓冲区的存在,在应用层向下发送一个数据包时,可以发送一次或者多次,即可以调用一次或者多次send。在应用层接收一个数据包时,可以接收一次或者多次,可以调用一次或者多次recv。发和收次数不需要对应。而TCP发送数据有自己的规则,如下。

        应用层调用传输层提供的接口发送一个数据块给TCP,数据块被写到了TCP的发送缓冲区。而TCP是以字节为单位看待这个数据块的。

        当数据块字节数太长,会被拆分称多个TCP数据包发送出去。

        当数据块字节数太短,先在缓冲区里等待,等待缓冲区长度差不多了或者其它适合的时机发送出去。

粘包问题

面向字节流会有一个问题:

        因为接收数据会按照TCP报头序号,在接收缓冲区里排好序,但是,在应用层在读数据的时候,可能读到的数据少于一个报文或者多余一个报文。

        因为它是按字节流的,要获取整个数据,可能需要多个报文分割出来的有效载荷。

        此时,一次读到的不是一个完整的报文,不好分离。 

  • TCP是按字节流的,想读取整个数据,可能需要读取多个报文分割出来的有效载荷。
  • 在TCP报文中没有明确报文长度,但是有序号字段。
  • 接收来的数据按照序号在接收缓冲区里排好序。
  • 应用层看到的是一连串的字节数据,不知道从哪部分开始,哪部分结束是一整个报文。

粘包问题就是:在应用层读数据的时候,可能会出现读的数据大于或者小于一个报文(request)的情况。

如何避免粘包问题:明确两个报文之间的边界。

  • 对于定长的报文,保证每次按照固定大小读取
  • 对于变长的报文,可以在报头位置,约定一个报文总长度的字段。
  • 对于编程的报文,还可以在报文之间明确分隔符,应用层协议,程序员写的,保证分隔符与正文不冲突即可。

对于http协议解决:

        在接收缓冲区中,一开始读到的肯定是http的报头。当读到空行说明报头读完了,在http报头中有一个字段Content_length记录了正文的字节数,按照这个读就可以读到整个报文。后面也按照这样读,就都可以都读到整个报文了。

        在分成多个字节recv到缓冲区。

比如:send一次,100字节。recv100次,一次recv一个字节。应用层就是先将接收缓冲区数据,去掉http报头,按照上面规则全部读出来,然后一个字节一个字节recv上去。

对于UDP协议,不会存在粘包问题。

        在UDP报头中,存在一个字段,记录了报文的总长度,UDP报头是定长的8字节。并且UDP是将数据一个一个交付给应用层的,会有数据之间很很明确的边界。一个报文就是一个数据。

TCP异常情况

        通信进程终止了:进程终止会释放文件描述符,套接字与文件有关,文件生命周期随进程,进程终止,相当于是关闭套接字,底层会自动触发四次挥手。

        机器重启:机器重启之前,需要将进程终止,所以和进程终止情况相同。

        机器掉电/网线断开:此时接收端认为连接还在,首先,一旦接收端向发送端发送数据,发现连接不在了,会发送RST报文给发送端。即使及手段没有写入动作,TCP内部内置了保活定时器,会定期询问对方是否还在,不在的话,会将连接释放。   

以上是关于TCP协议面试热点(面向字节流,粘包问题,TCP异常情况)的主要内容,如果未能解决你的问题,请参考以下文章

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

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

实战说明TCP协议栈的数据包拆包粘包问题

带你了解面试高频TCP协议——详解

带你了解面试高频TCP协议——详解

带你了解面试高频TCP协议——详解