我正在编写客户端 - 服务器程序。服务器select()
在readfd1
等待readfd1
准备就绪。如果准备就绪,服务器正在收集数据并打印。一段时间内一切都很好,但一段时间后,套接字recv()
失败,errno
设置为ETIMEDOUT
。现在我想重写我的程序以阻止这些错误条件。所以我经历了Richard Stevens的“Unix网络编程”,其中列出了select()
取消阻止的4个条件。以下是引起我注意的两个条件
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()
是否有效?
答案 0 :(得分:3)
如果recv()
返回0,则另一端主动且优雅地关闭连接。
如果recv()
返回-1,则连接上可能存在(可能)错误,并且不再可用。
这意味着您可以判断关闭连接的对等方与连接上发生的错误之间的区别。在这两种情况下,常见的做法是close()
套接字的结尾。
还有两点需要考虑:
如果recv()
返回-1,则应检查errno,因为它可能不表示真正的错误。
如果您将套接字置于非阻塞模式,则errno
可以是EAGAIN/EWOULDBLOCK
;如果系统调用被信号中断,则EINTR
可以是errno
。所有其他recv()
值表示连接已断开,您应该将其关闭。
TCP可以半双工运行。如果对等体仅关闭了连接的写入端,shutdown()
将在您的末尾返回0。常见的做法是将连接视为已完成,并关闭连接的末尾,但您可以继续写入它,另一端可以继续从中读取。是否仅关闭TCP连接的读取或写入结束由{{1}}函数控制。
答案 1 :(得分:1)
套接字错误并不一定意味着连接已关闭,例如考虑如果您和对等方之间的网络电缆被切断会发生什么情况,那么通常会出现ETIMEDOUT
错误。大多数错误都是不可恢复的,因此几乎总是建议在错误时关闭连接结束。
select
可以取消阻止时两种状态之间的差异,是因为另一端以一种很好的方式关闭了它们的连接(第一种情况),或者存在一些实际错误(第二种情况)。