TCP异常处理

254 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第33天,点击查看活动详情

大家好,我是bug郭,一名双非科班的在校大学生。对C/JAVA、数据结构、Spring系列框架、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流

作者简介:

面向字节流

TCP是面向字节流读取数据的,也就导致了一个粘报问题! 所有的面向字节流都会存在粘包问题!

粘包问题: 在这里插入图片描述 当主机A发送3条数据给主机B时,3条数据就来到了主机B的接收缓冲区,然后应用程序通过socket中的read方法读取数据,面向字节流读取,这时应用程序也无法区分数据包,就出现了粘包问题!

如何解决呢? 显然我们的应用层数据拿到的数据时进行了分用的,也就是说并没有TCP协议中的字节确认序号,所以这里要通过对应用层协议的改进才能解决粘包问题! 在设计应用层协议时就要对数据通过标记位或者分隔符进行分割! 在这里插入图片描述 在应用层协议设计好就处理了粘包问题! 如果我们是基于某些库和框架来完成的网络通信,一般来说粘包问题已经被库和框架解决了,如果你是自己实现的库和框架使用TCP协议那就需要考虑粘包问题!

TCP的异常处理

  • 进程终止 当我们强制杀死一个进程时,这时的TCP连接是咋样呢? TCP连接是通过Socket来建立的,Socket本质是进程打开的一个文件,而文件就存在于进程的PCB中的文件描述符表,每次打开一个文件(包括Socket)就会在文件描述符表中添加一项! 每次关闭一个文件就在文件描述符表中删除该项! 如果直接杀死进程,PCB也就没了,文件描述符表自然没了,相当于手动调用了socket.close效果一样!
  • 机器关机 关机机器会先通过操作系统将主机中的所有进程强制结结束也就和上述的进程终止一样,然后再关机
  • 机器掉电/网线断开 机器掉就是电台式机拔掉了电源 操作系统毫无防备,没有对该进程处理后事! 在这里插入图片描述 主机B接收方挂了 主机A并不知道该主机已经断电! 一直在等待ACK然后进行超时重传,重传失败几次后就会重新建立连接,最后发现无济于事就断开了连接! 在这里插入图片描述 主机A发送方挂了,主机B并不知道是什么原因是A休息了,还是A挂了! 主机B就会时不时发送一个小的报文(不带数据的,只为触发ACK)心跳报探测报文,当A不再放回ACK就认为A出现了问题,就断开连接!

TCP和UDP对比

  • TCP适用场景 对可靠性有一定要求(日常大部分开发都是基于TCP)
  • UDP适用场景 对可靠性要求不高,对于效率要求高(机房中主机间通信,分布式系统)

经典面试题 基于UDP如何实现可靠传输(其实在考TCP) 本质就是在应用层协议中基于UDP实现TCP的机制! 确认应答... UDP是操作系统中已经实现的不能更改,只能更改应用层协议!