Как определить, было ли закрыто соединение с сокетом



Я пишу сокет с C++ под Linux. У меня есть вопрос. Как я могу узнать, закрыл ли клиент соединение.



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

Вот пример моей программы:



 newsockfd = accept(sockfd, 
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);


Также у меня есть несколько сокетов на моем сервер. Мне нужно знать, к какому разъему клиент закрыл соединение.

678   3  

3 ответов:

Если клиент закрыл соединение, n = read(newsocketfd, buffer, 255) вернет 0.

Вы можете установить сокет на таймаут, используя "setsockopt". Вам нужно будет #включить sys/socket.h и sys/types.h

int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); 

Вы хотите SO_RCVTIMEO и SO_SNDTIMEO для optname. Для optval вам понадобится указатель на struct timeval, а level-SOL_SOCKET. Например:

struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;

setsockopt(mySocket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); 

Установит сокет на тайм-аут для операций отправки через 10 секунд.

Вы хотите использовать select или poll на ваших сокетах, а не просто чтение. Таким образом, медленный клиент не блокирует весь сервер.

Вы также захотите отслеживать все ваши сокеты.

Мой основной псевдокод для серверов с несколькими сокетами выглядит следующим образом:

<create/bind serversocket, listen on it, add it to fd_set>

while ( running )
{
   nd = select( maxfd, fd_set, null, null, timeout )
   if ( nd == 0 )
      continue;  // timeout - do periodic processing
   if ( fd_isset( fd, serversocket )
   {
       do the accept on the server socket and add new socket to the fd_set
   }
   if ( isset( fd, clientsocket ) )
   {
       now you know data is available on the socket, so you can read from it
       a return of 0 on the socket indicates the socket was closed
       in which case you should close your end and remove socket from fd_set
   }
}
Я опускаю много деталей, но это основная структура.

Comments

    Ничего не найдено.