Обеспокоенность по поводу обработки плохого вызова принять () - PullRequest
2 голосов
/ 29 марта 2011

Я пишу сервер MUD для личного обучения, и, к счастью, мне удалось объединить сокет в пару классов, и все, кажется, работает правильно;сервер прослушивает и принимает соединения, и в настоящее время принимает текст от клиента и отправляет его обратно.

Дело в том, что я не совсем уверен, что делать с вызовом метода accept (), который возвращает что-то отличное отWSAEWOULDBLOCK или действительный сокет.Должен ли я просто сбросить новый сокет на 0 и вернуться, возможно, с сообщением об ошибке, в котором говорится, что случилось что-то плохое?Это то, что я сейчас делаю, с добавлением: если это произойдет 20 раз, я выключу сервер.

void MUDControlSocket::Poll()
{
   // create a new connection here
   timeval timeout;

   FD_ZERO(&ReadSet);
   FD_ZERO(&WriteSet);
   FD_ZERO(&ExceptionSet);

   TopSocket = GetSocket();
   NewSocket = 0;
   FD_SET( GetSocket(), &ReadSet );

   if( SocketList.size() > 0 )
   {
      for( sockIter iter = SocketList.begin(); iter != SocketList.end(); ++iter )
      {
         FD_SET((*iter)->GetSocket(), &ReadSet);
         FD_SET((*iter)->GetSocket(), &WriteSet);
         FD_SET((*iter)->GetSocket(), &ExceptionSet);
         TopSocket = (*iter)->GetSocket();
      }
   }

   if( select( TopSocket+1, &ReadSet, &WriteSet, &ExceptionSet, &timeout ) == SOCKET_ERROR )
   {
      cout << "Error on select() call: " << SocketErrorType(WSAGetLastError()) << endl;

      delete this;
      exit(EXIT_FAILURE);
   }

   // as long as everything is working correctly, this if block should always be entered UNLESS a new connection is accepted
   if( (NewSocket = accept(GetSocket(), NULL, NULL) ) == INVALID_SOCKET )
   {
      if( WSAGetLastError() == WSAEWOULDBLOCK ) // it's not an actual problem. just nothing to connect to yet
         return;
      NewSocket = 0;
      static int count = 0;
      cout << "Error on accepting new connection: " << SocketErrorType(WSAGetLastError()) << endl;
      if( ++count >= 20 )
         done = true;
      return;
   }

   SocketList.push_back(new MUDSocket(NewSocket)); // only happens if accept DOES NOT return a value of INVALID_SOCKET i.e. a new connection was accepted
   TopSocket = NewSocket;
   NewSocket = 0;
}

TopSocket и NewSocket имеют тип SOCKET и объявлены в области видимости файла.SocketList является стандартным списком MUDSocket *, а MUDControlSocket является производным от MUDSocket как синглтон.

Дайте мне знать, если вам нужна дополнительная информация, и спасибо за любую помощь.

Ответы [ 3 ]

0 голосов
/ 29 марта 2011

Некоторые другие ошибки, возможные из accept, заключаются в том, что памяти мало, количество соединений исчерпано и т. Д., И т. Д.

Возможно, это можно устранить, закрыв неиспользуемые или забытые соединения, или просто указави выбрасывает исключение.

0 голосов
/ 29 марта 2011

Во-первых: не устанавливайте сокет в 0: это допустимый fd для сокетов в некоторых * системах NIX, и это плохая привычка.Предположим, что единственный неверный сокет fd равен -1.Если вы сделаете что-нибудь еще, то позже вы получите настоящие ошибки в реальном программном обеспечении (поверьте мне: я говорю из опыта отладки кода, который использовал 0 в качестве неверного сокета fd).

Кроме этого, я бы сказал,Вызовите исключение: accept не должно завершиться ошибкой, если у вас не хватает ресурсов, что должно быть как исключением, так и ошибкой.C ++ имеет механизм для обработки таких вещей, и это исключения.

Кстати: delete this почти всегда очень плохая идея, выход из середины вашего кода может затруднить отладку (бросить исключение ввместо) и позвольте вызывающему сделать выход, если это необходимо) и вместо попытки принять сокет с accept вы можете использовать select, чтобы сказать вам, есть ли что-то, чтобы принять - и убрать обработку специального случаяфункции, чтобы выбрать только там.Вы можете пойти немного дальше и внедрить специализированный шаблон наблюдателя (как я это делал на моем подкасте около месяца назад), чтобы попрактиковаться не только в своем сетевом коде, но и в своих шаблонах проектирования.Это также поможет сделать ваш код более переносимым и использовать его позже.

HTH

0 голосов
/ 29 марта 2011

Верните ошибку и дайте вызывающему коду правильно с ней справиться.

...