2

我正在编写一个客户端-服务器程序。服务器正在等待select()读取准备就绪。如果它准备好了,服务器正在收集数据并打印。暂时一切都很好,但过了一段时间,socket设置为失败。现在我想重写我的程序来阻止这些错误条件。所以我浏览了 Richard Stevens 的“Unix Network Programming”,其中说明了解除阻塞的 4 个条件。以下是引起我注意的两个条件readfd1readfd1recv()errnoETIMEDOUTselect()

A. client sent FIN, here return value of `recv()` will be `0`
B. some socket error, here return value of `recv()` will be `-1`.

我的问题是,套接字错误会关闭连接吗?如果是这样,那么为什么以上两个条件是分开的。如果没有,recv()套接字上的 next 工作吗?

4

2 回答 2

3

如果recv()返回 0,则表示另一端已经主动优雅地关闭了连接。

如果recv()返回 -1,则(可能)连接出现错误,并且不再可用。

这意味着您可以区分关闭连接的对等方和连接上发生的错误。在这两种情况下,最常见的做法是连接到close()套接字的一端。

不过还有两点需要考虑:

recv()返回 -1 的情况下,您应该检查 errno,因为它可能并不表示真正的错误。 errno可能是EAGAIN/EWOULDBLOCK您已将套接字置于非阻塞模式,也可能是EINTR系统调用被信号中断。所有其他errno值表示连接已断开,您应该关闭它。

TCP 可以半双工运行。如果对等方仅关闭了它的连接写入端,则recv()在您的端返回 0。常见的做法是将连接视为已完成,并关闭连接的一端,但您可以继续写入,另一端可以继续读取。是否只关闭 TCP 连接的读取端或写入端由该shutdown()函数控制。

于 2013-05-29T13:03:10.230 回答
1

套接字错误并不一定意味着连接已关闭,例如,考虑一下如果您和您的对等方之间的网络电缆以某种方式被切断,那么您通常会收到该ETIMEDOUT错误会发生什么。大多数错误是不可恢复的,因此几乎总是建议在错误时关闭连接端。

两种状态之间的区别何时select可以解除阻塞,是因为另一端以一种很好的方式关闭了它们的连接(第一种情况),或者存在一些实际错误(第二种情况)。

于 2013-05-29T13:04:00.933 回答