粘包问题其实并不是TCP独有的的问题而是每一个面向字节流都会出现的问题,那么什么是粘包问题呢?请看下图
这里我们表示一个字节流这里面的消息就是我们即将发送的消息,那么这里面就是以字节为单位的数据,但是我们知道计算机在某一时刻传输多少字节是不知道的,我们并不知道自己的这些信息一次会被发出去多少,假如说按照我输入的情况我第一次要发送的是aaa第二次是bbb但是由于上面情况的发生,因此我们发送的情况可能是第一次发送的数据是aa第二次是abbb。这也是很有可能的,而第二次发送的数据abbb其实就是两个包黏在一起了。我们称之为粘包问题。那么该如何去避免粘包问题呢?那就是明确每个数据包的边界,也就是说做数据得有边界感,那么如何去明确边界呢?有以下两种方式。
第一种就是用分隔符来表示,这里我们结合一个生活中实际的例子来说明,那就是我们在写作文的时候,由于我们写作文一写就可能很长,那么用分隔符来表述其实就是在作文里加上逗号,问号,或者句号这一类的标点符号,那么粘包问题大家就可以想象成去读一篇没有标点符号的文章,读起来肯定是相当的难受,因为你在读的时候就可能出现了粘包问题。那么分隔符分割就是用标点符号把每句话进行了分割从而使得可以读起来知道每句话的边界在哪儿。
用数字代表长度是什么样子的呢?我们依然是以上面的那个内容为例
这里面还是我们要发送的数据,那么这时候我们发送的数据有什么特点呢?那就是我们每一次要发送出去的数据前面都有一个数字,这个数字表示了我们要发送的数据的长度,而有了长度也就有了边界了,每一次的发送我们只需要读取一下前面的数字就可以了。
进程终止那么TCP连接是如何断开的呢?其实当一个进程终止之后,这个进程所获取的资源自然也就被释放掉了,那么操作系统内核就会进行连接的释放也就是四次挥手。这里我们要知道一个概念那就是,TCP连接是否存在和进程是否存在是没有必然联系的,因为TCP连接是独立于进程存在的,这是为什么呢?因为连接的构建本质上是内核进行完成的,就像我们用电话,和别人打电话,当我们的电话挂断后我们的电话线依然是存在的,而我们在写代码的时候也确实并没有去在代码里建立连接我们是直接调用了接口然后把参数传给操作系统内核让内核去建立连接。我们可以理解为,连接的建立是两个操作系统建立的,而进程只是利用这个连接进行通信的。因此进程结束并不一定意味着操作系统会删除对方信息,从而断开连接。因此,TCP连接具有独立性和持久性。
如果是正常状态关机那么在关机前操作系统会将所有的正在运行的程序全部终止,那么这时候其实就是上面进程终止的情况。
什么是非正常情况关机呢?比如说你的事台式电脑然后突然断电了,这种情况下操作系统没有足够的时间去终止程序进行四次挥手,也就是说此时,接收端看你迟迟没有任何的数据发送过来,然后就会进行等待,当等待的时间过长之后那么接收端那方就会自动断开连接。
电脑断网,这种情况和上述其实差不多接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就
会进行reset。即使没有写入操作,TCP自己也内置了一个保活定时器,会定期询问对方是否还在。如果
对方不在,也会把连接释放。
另外,应用层的某些协议,也有一些这样的检测机制。例如HTTP长连接中,也会定期检测对方的状
态。例如QQ,在QQ断线之后,也会定期尝试重新连接