17 | TCP并不总是“可靠”的?
该思维导图由 AI 生成,仅供参考
TCP 是可靠的?
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了TCP协议的可靠性问题,并指出了一些常见的“不可靠”情况。作者首先解释了TCP协议并非完全可靠的原因,包括发送端无法获取对端数据流的ACK情况,以及接收端无法保证ACK过的数据部分可以被应用程序处理等问题。文章总结了网络中断和系统崩溃造成的对端无FIN包的情况,并提出了相应的解决方法。此外,还详细讨论了对端有FIN包发出的情形,并给出了相关的代码示例。通过实验验证,作者展示了通过read和write操作来感知异常情况的方式,以及对应的处理方式。总的来说,本文通过具体的案例和技术细节,深入剖析了TCP协议的可靠性问题,为读者提供了深入了解TCP协议的实用知识。文章内容丰富,对TCP协议的异常情况进行了详细分析,对读者了解TCP协议的实际应用具有重要参考价值。
《网络编程实战》,新⼈⾸单¥59
全部留言(36)
- 最新
- 精选
- 传说中的成大大看到后面我好像理解了我上面那个提问,当崩溃重启过后是重新三次握手建立连接,创建新的套接字,只是在网络上传输的包,因为是通过ip地址和端口方式进行的寻址,所以新连接上去的客户端会接收到之前还没接收到的包,然后新连接的客户端没有这些包的tcp分组信息所以就会给服务器端(对端)发送一个RST
作者回复: 正解。
2019-09-09418 - melon最后的例子没有触发SIGPIPE,是因为老师例子设计的有点儿瑕疵。client 在不断的发送数据,server 则每次接受数据之后都 sleep 一会,也就导致接收速度小于发送速度,进而导致 server 终止的时候接收缓冲区还有数据没有被读取,server 终止触发 close 调用,close 调用时如果接收缓冲区有尚未被应用程序读取的数据时,不发 FIN 包,直接发 RST 包。client 每次发送数据之后 sleep 2秒,再试就会出SIGPIPE 了。
作者回复: 所以需要在客户端程序里加sleep就可以了?
2020-07-15317 - linker我的电脑,结果也是一样的, 第二个问题,服务器正常关闭,客户端应该是受到了fin包,read返回eOF,wirte返回rst
作者回复: 说明新版的内核在这些特性上有所改进。
2020-03-2129 - 盘尼西林没有理解 reset by peer 和 broken pipe 的区别。。
作者回复: 一个是TCP RST的状态异常,一个是SIGPIPE 信号将进程进行回收。
2020-01-069 - tim>>"但是,发送端并无法获取对应数据流的 ACK 情况" 对上面这段话不理解,TCP 的 ACK不是带着序号的吗?发送端根据这个序号能计算出是哪次发送的ACK。 哪位大牛能解释一下吗?
作者回复: 这里是从应用层报文数据角度出发来说的,因为数据是一个流,没有办法判断数据的哪些部分没对端收到。 从TCP角度来说,确实是通过ACK来感知TCP包的接收情况的。
2019-10-0945 - geraltlaush老师,你文章的案例默认fd都是阻塞的吧,如果是非阻塞的话,返回的n < 0 不一定是错误啊
作者回复: 到现在为止,都是阻塞的,后面会切成非阻塞的。
2019-10-1323 - Jasonerror(1, 0, "usage: reliable_client01 <IPaddress>");这个error函数,具体是什么作用?
作者回复: 根据错误码打印错误信息,并且可以退出当前程序。
2020-07-062 - yang老师 我提一个read直接感知FIN包的疑问哈: 我停留在 stdin这里 等我输入完之后,就能调用read感知到对端已经关闭了呀? 是因为等到stdin之后,再感知是不是太晚了呀?
作者回复: 这就是为什么需要使用select、poll等事件分发机制,正确的解法是一旦有事件发生,比如这里read读到EOF,就应用直接去处理此类事件,而不是阻塞在这里等待用户的输入。好消息是,很快我们就会详细学习这部分内容了。
2019-09-162 - 徐凯第二题 客户端--------服务器 1. 客户端发送FIN包,处于发送缓冲区的数据会逐一发送(可能通过一次或多次write操作发送),FIN包处于这段数据的末尾,当数据到达接收端的接收缓冲区时,FIN起到了一个结束符的作用,当接收端接收数据时遇到FIN包,read操作返回EOF通知应用层。然后接收端返回一个ACK表示对这次发送的确认。(此时客户端进入FIN_WAIT1,服务端进入CLOSE_WAIT状态) 2. 客户端接收到ACK之后,关闭自己的发送通道,客户端此时处于半关闭状态。等待服务器发送FIN包。 (客户端进入FIN_WAIT2状态) 3. 服务端发送FIN包,同上类似处于发送缓冲区的内容会连同FIN包一起发过去,当客户端接收成功后同时将FIN解析为EOF信号使得上层调用返回。(客户端进入TIME_WAIT状态 服务端进入LAST_ACK状态) 4. 客户端等待2MSL的时间,在此期间向服务器发送ACK。如果丢包进行重传。如果服务器收到ACK后 服务器进入CLOSED状态 客户端也进入CLOSED状态。 5. 连接关闭 我想问一下 如果最后一次挥手一直丢包 在2MSL的时间内都没到 TCP会咋办 会重置计时器么 还是就不管了直接关闭呢
作者回复: 我猜想是会直接关闭的,没有对ACK的ACK包。
2019-09-1121 - yusuf# uname -a Linux tst 3.10.0-957.21.3.el7.x86_64 #1 SMP Tue Jun 18 16:35:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux # # ./reliable_client01 127.0.0.1 good peer connection closed # # ./reliable_client01 127.0.0.1 bad bad bad2 peer connection closed # # ./reliable_client02 127.0.0.1 send into buffer 19 send into buffer -1 send error: Connection reset by peer (104)
作者回复: 基本和我的Linux下结果一致。
2019-09-091