面向字节流
粘包问题
在面向字节流的情况下,会产生一些其他的问题:粘包问题,这里“粘”的是“应用层数据报”,通过TCP read/write的数据,都是TCP报文的载荷,也就是应用层数据。
发送方一次性是可以发送多个应用层数据报的,但是接受的时候,如何区分,从哪里到哪里是一个完整的应用层数据报?如果没设计好,接收方就很难区分,甚至产生bug!
那么如何避免粘包问题呢?归根结底就是一句话,明确两个包之间的边界。
此处正确的做法,是合理地设计应用层协议,这件事本身在传输层这边已经无解了,需要站在应用层的角度,来解决这个问题
1.应用层协议中,引入分隔符,区分包之间的边界。
比如\n
2.应用层协议中,引入"包长度”,也能区分包之闻的边界。
比如使用最开头固定的2个字节表示包的长度,0x0003aaa
粘包问题不仅仅是TCP才有的,只要是面向字节流的机制(文件)也有同样的问题,解决方案也都是一样。要么使用分隔符,要么使用长度
TCP异常情况
网络本身就会存在一些变数,导致TCP连接不能继续正常工作了。以下是出现那些情况时TCP如何处理使其正常
- 进程崩溃
进程就没了=>PCB没了=>文件描述符表也就被释放了=>相当于调用了socket.close()
,socket在系统内核也是一个文件,也会被放到文件描述符表中=>崩溃的一方就会发出FIN,进一步触发四次挥手,此时连接就正常释放了。此时TCP的处理和进程正常退出没啥区别
- 主机关机(正常步骤的关机)
正常关机,就会先尝试干掉所有的进程(强制终止进程),就和上述所说的崩溃的处理是一样的。主机关机会有一定的时间,在这个时间内四次挥手可能是挥完的,如果没挥完也没事
- 主机掉电(拔电源,没有任何反应的机会)
电脑瞬间黑了,此时自然就没有任何可以操作的空间了。
此处就涉及到"心跳包”,B这边虽然是接收方,也会周期性的给对方发起一个 不携带任何 业务数据(载荷)TCP数据报
发起这个包的目的,就是为了触发ACK,就是确认一下A是否正常工作/确认网络是否畅通.
- 网线断