select表示在绝对不是实际上已经关闭的情况下准备好读取套接字

问题描述

| 在我的服务器中,我使用
select()
确定是否准备好读取任何套接字。结果,每次循环都会执行主循环“ 0”。 为了测试服务器,我编写了一个简单的客户端,该客户端仅发送一条消息,然后退出。顺便说一句。我使用协议缓冲区发送信息-消息表示此库中类型为Message的对象。 测试会话如下所示:
select()
服务器的套接字已准备好读取
accept()
客户插座 从客户端的套接字读取消息
select()
服务器的套接字未准备好读取,客户端的套接字已准备好 从客户端的套接字读取消息 最后一步是错误的,因为客户端已经关闭了连接。结果,protobuf库获得
Segmentation fault
。我想知道为什么FD_ISSET在关闭时在步骤6中说套接字已准备好。如何检查插座是否关闭? 编辑: 我发现了如何检查插座是否打开
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd,SOL_SOCKET,SO_ERROR,&error,&len );
    

解决方法

        如果远程对等方关闭了套接字,则它是“可读的”,您需要调用
recv
并处理返回错误的情况和返回0的情况,这表明对等方关闭了连接。时尚有序。 读取
SO_ERROR
sockopt的方法不正确,因为它会返回当前的挂起错误(例如,来自非阻塞的
connect
)     ,        当有要读取的数据或有要读取的EOF时(即对等方关闭连接),用于客户端与服务器之间的通信的套接字将被标记为可读(即select()将返回)。 当select()返回并且您的fd被标记时,只需read()即可。如果read()返回一个正数,则表示您有数据。如果返回0,则得到EOF。如果它返回-1,则说明您有问题(除非errno为EAGAIN)。