2013-05-29 88 views
2

我正在编写一个客户机 - 服务器程序。服务器为select()readfd1等待readfd1的准备就绪状态被读取。如果准备就绪,服务器正在收集数据并打印。一切都很好,但一段时间后,套接字recv()失败,errno设置为ETIMEDOUT。现在我想重写我的程序来挫败这些错误状况。所以我经历了Richard Stevens的“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`. 

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

回答

3

如果recv()返回0,另一端已主动正常关闭连接。

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

这意味着您可以分辨关闭连接的同伴与连接上发生的错误之间的差异。在这两种情况下都需要做的事情是在你的socket的末尾使用close()

有2个点,但考虑:

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

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

1

套接字错误并不一定意味着连接已关闭,请考虑例如发生了什么情况,如果以某种方式切断了您与对等体之间的网络电缆,则通常会出现ETIMEDOUT错误。大多数错误是不可恢复的,所以关闭错误连接的结束几乎总是可取的。

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