select говорит, что сокет готов к чтению, когда его точно нет (на самом деле он уже закрыт) - PullRequest
3 голосов
/ 23 июня 2011

На своем сервере я проверяю, готов ли какой-либо сокет к чтению, используя select(), чтобы определить его.В результате основной цикл select() выполняется каждый раз, когда он повторяется.

Для проверки сервера я написал простой клиент, который отправляет только одно сообщение, а затем завершает работу.КСТАТИ.Я использую буферы протокола для отправки информации - сообщение означает объект класса типа Message в этой библиотеке.

Сеанс теста выглядит следующим образом:

  1. select()
  2. сокет сервера готов к чтению
  3. accept() сокет клиента
  4. чтение сообщения из сокета клиента
  5. select()
  6. сокет сервера не готов к чтению, клиентскийодин готовый
  7. чтение сообщения из клиентского сокета

Последний шаг неверен, поскольку клиент уже закрыл соединение.В результате библиотека 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 );

Ответы [ 2 ]

11 голосов
/ 23 июня 2011

сокет является «читаемым», если удаленный узел закрывает его, вам необходимо вызвать recv и обработать как случай, когда он возвращает ошибку, так и случай, когда он возвращает 0, что указываетчто узел однозначно завершил соединение.

Чтение sockopt SO_ERROR не является правильным способом, так как он возвращает текущую ожидающую ошибку (например, из неблокирующей connect)

1 голос
/ 23 июня 2011

Сокет, используемый для связи между клиентом и вашим сервером, будет помечен как читаемый (т. Е. Select () вернется), когда есть данные для чтения, или , когда есть EOF для чтения (т.е.peer закрыл соединение).

Просто прочитайте (), когда select () вернется, и ваш fd будет помечен.Если read () возвращает положительное число, вы получили данные.Если он возвращает 0, вы получили EOF.Если он возвращает -1, у вас есть проблема (если только errno не EAGAIN).

...