select表示套接字已经准备好读取了,但它肯定不是(实际上已经关闭了)

时间:2021-05-11 13:25:59

In my server I check if any socket is ready to read using select() to determine it. As a result in main loop select() is executed every time it iterates.

在我的服务器中,我使用select()检查是否有任何套接字准备读取。因此,每次迭代时都会执行主循环select()。

To test the server I wrote a simple client that sends only one message and then quits. BTW. I use protocol buffers to send information - message means an object of type class Message in this library.

为了测试服务器,我编写了一个简单的客户机,它只发送一条消息,然后退出。顺便说一句。我使用协议缓冲区来发送信息——消息表示这个库中的类消息类型的对象。

The test session looks like:

测试过程如下:

  1. select()
  2. select()
  3. server's socket ready to read
  4. 服务器的套接字准备读取
  5. accept() client's socket
  6. accept()客户端的套接字
  7. read message from client's socket
  8. 从客户端套接字中读取消息
  9. select()
  10. select()
  11. server's socket not ready to read, client's one ready
  12. 服务器的套接字尚未准备好读取,客户端的套接字已准备好
  13. read message from client's socket
  14. 从客户端套接字中读取消息

The last step is wrong because client has already closed connection. As a result protobuf library gets Segmentation fault. I wonder why FD_ISSET says the socket is ready in step 6 when it is closed. How can I check if a socket is closed?

最后一步是错误的,因为客户端已经关闭了连接。这样使得protobuf库出现了分割错误。我想知道为什么FD_ISSET说在第6步关闭时套接字已经准备好了。如何检查插座是否已关闭?


EDIT:

编辑:

I've found how to check if the socket is open

我找到了如何检查插座是否打开的方法

int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len );

2 个解决方案

#1


11  

the socket is "readable" if the remote peer closes it, you need to call recv and handle both the case where it returns an error, and the case where it returns 0, which indicates that the peer shut down the connection in an orderly fashion.

如果远程对等点关闭套接字,则需要调用recv并处理返回错误的情况和返回0的情况,这表明对等点以有序方式关闭连接。

Reading the SO_ERROR sockopt is not the correct way, as it returns the current pending error (from, eg. a non-blocking connect)

读取SO_ERROR sockopt不是正确的方法,因为它返回当前挂起的错误(例如,from)。一个非阻塞的连接)

#2


1  

The socket used for communication between a client and your server will be flagged as readable (i.e. select() will return) when there is data to read, or when there's an EOF to read (i.e. the peer closed the connection).

用于客户端和服务器之间通信的套接字将被标记为可读(即select()将返回),当有数据要读取时,或当有EOF要读取时(即对等端关闭连接)。

Just read() when select() returns and your fd is flagged. If read() returns a positive number, you got data. If it returns 0, you got EOF. If it returns -1, you have a problem (unless errno is EAGAIN).

只要在select()返回时读(),然后标记fd。如果read()返回一个正数,就会得到数据。如果它返回0,你得到EOF。如果返回-1,就会出现问题(除非errno再次出现)。

#1


11  

the socket is "readable" if the remote peer closes it, you need to call recv and handle both the case where it returns an error, and the case where it returns 0, which indicates that the peer shut down the connection in an orderly fashion.

如果远程对等点关闭套接字,则需要调用recv并处理返回错误的情况和返回0的情况,这表明对等点以有序方式关闭连接。

Reading the SO_ERROR sockopt is not the correct way, as it returns the current pending error (from, eg. a non-blocking connect)

读取SO_ERROR sockopt不是正确的方法,因为它返回当前挂起的错误(例如,from)。一个非阻塞的连接)

#2


1  

The socket used for communication between a client and your server will be flagged as readable (i.e. select() will return) when there is data to read, or when there's an EOF to read (i.e. the peer closed the connection).

用于客户端和服务器之间通信的套接字将被标记为可读(即select()将返回),当有数据要读取时,或当有EOF要读取时(即对等端关闭连接)。

Just read() when select() returns and your fd is flagged. If read() returns a positive number, you got data. If it returns 0, you got EOF. If it returns -1, you have a problem (unless errno is EAGAIN).

只要在select()返回时读(),然后标记fd。如果read()返回一个正数,就会得到数据。如果它返回0,你得到EOF。如果返回-1,就会出现问题(除非errno再次出现)。