问题描述
|
在我的服务器中,我使用
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)。