我正在写一个客户端服务器程序。 服务器在readfd1
上select()
,等待readfd1
读取的准备就绪。 如果准备就绪,服务器正在收集数据并打印。 一切都很好,但一段时间后,套接字recv()
失败,设置为ETIMEDOUT
errno
。 现在我想重写我的程序来阻止这些错误状况。 所以我通过理查德·史蒂文斯(Richard Stevens)的“Unixnetworking编程”(Unix Network Programming)说明了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`.
我的问题是,套接字错误closures连接? 如果是这样的话,为什么上述两个条件是分开的。 如果没有,套接字上的下一个recv()
是否工作?
如果recv()
返回0,则另一端主动正常关闭连接。
如果recv()
返回-1,那么连接上可能有(可能)错误,并且不再可用。
这意味着您可以分辨关闭连接的同伴和连接上发生的错误。 在这两种情况下通常要做的就是close()
你的socket端。
还有两点需要考虑:
在recv()
返回-1的情况下,您应该检查errno,因为它可能不表示真正的错误。 如果您将套接字置于非阻塞模式,那么errno
可以是EAGAIN/EWOULDBLOCK
如果系统调用被信号中断,则可以是EINTR
。 所有其他的errno
值意味着连接中断,您应该关闭它。
TCP可以在半双工模式下运行。 如果对方只关闭连接的写入端,则recv()
在您的结尾处返回0。 常见的做法是将连接视为已完成,并关闭连接的结束,但可以继续写入连接,另一端可以继续读取连接。 是否仅关闭TCP连接的读取或写入结束由shutdown()
函数控制。
一个套接字错误并不一定意味着连接已经关闭,举个例子,如果你和对方之间的网络连接断开了,你会发现ETIMEDOUT
错误。 大多数错误是不可恢复的,所以关闭错误连接的结束几乎总是可取的。
当select
可以解除阻塞时,两个状态之间的区别是因为另一端以一种很好的方式关闭它们的连接(第一种情况),或者存在一些实际的错误(第二种情况)。