1

当数据包传送永久失败时,TCP/IP 如何报告错误?我见过的所有 Socket.write() API 都只是将字节传递到底层 TCP/IP 输出缓冲区并异步传输数据。那么,如果数据包传送永久失败(即目标主机不再可达),TCP/IP 应该如何通知开发人员?

任何要求发送方等待来自远程端确认的协议都会收到一条错误消息。但是对于发送方不必从目的地读取任何字节的协议会发生什么呢?TCP/IP 是否只是静默失败?也许 Socket.close() 会返回错误?TCP/IP 规范对此有任何说明吗?

4

4 回答 4

5

TCP/IP 是一种可靠的字节流协议。您的所有字节都将到达接收器,否则您将收到错误指示。

错误指示将以关闭套接字的形式出现。无论采用何种通信模式(谁进行发送),如果无法传递字节,则套接字将关闭。

那么问题来了,你怎么看socket关闭了?如果您从不阅读,您最终会在尝试写入已关闭的套接字时出错(我认为使用 ECONNRESET errno)。

如果您需要休眠或等待另一个文件句柄的输入,您可能希望在 select() 调用中等待,在该调用中将套接字包含在您正在等待的源列表中(即使您从未预料到接收任何东西)。如果 select() 指示套接字已准备好进行读取调用,您可能会得到 -1 返回(我认为使用 ECONNRESET)。EOF 表示有序关闭(另一端执行了 shutdown() 或 close()。

如何区分此错误关闭和干净关闭(例如,其他程序退出)?errno 值可能足以区分错误和有序关闭。

如果您想要一个明确的问题指示,您可能需要在套接字层之上构建某种应用程序级协议。例如,接收方发送回发送方的简短“确认”消息。然后违反更高级别的应用程序协议(发件人没有看到确认)将确认这是错误关闭与干净关闭。

于 2008-10-08T04:14:28.483 回答
4

套接字 API 无法准确地通知写入者已收到多少字节作为对等方的确认。存在成功shutdownclose两者中的任何一个都不能保证。

TCP/IP 规范没有说明应用程序接口(几乎总是套接字 API)。

SCTP是 TCP 的替代方案,它试图解决这些缺点等。

于 2008-10-08T04:02:50.177 回答
0

在 C 中,如果您写入一个使用 send() 失败的套接字,您将返回已发送的字节数。如果这与您要发送的字节数不匹配,那么您就有问题了。但是,当您写入失败的套接字时,您会返回 SIGPIPE。在开始套接字处理之前,您需要有一个信号处理程序,当您获得 SIGPIPE 时会提醒您。

如果你从一个套接字读取,你真的应该用一个警报来包装它,这样你就可以超时。像“alarm(timeout_val); recv(); alarm(0)”。查看recv的返回码,如果为0,表示连接已经关闭。返回负数表示读取失败,需要检查errno。

于 2008-10-08T04:09:42.487 回答
0

TCP 建立在 IP 协议之上,该协议是 Internet 的核心,提供驱动路由的大部分互操作性,这决定了如何将数据包从源端获取到目的地。IP 协议指定在数据包无法到达发送者的情况下,应通过 Internet 控制消息协议 (ICMP) 将错误消息发送回发送者。其中一些原因包括生存时间 (TTL) 字段递减为零,这通常意味着数据包卡在路由循环中,或者由于交换机争用导致缓冲区溢出而丢弃数据包。正如其他人所说,Socket API 负责在 IP 层将这些错误中继到在 TCP 层与网络交互的应用程序。

于 2008-10-08T04:30:34.677 回答