2

我正在为个人学习目的编写一个MUD服务器,我很高兴地设法将套接字的东西打包成几个类,并且一切似乎都正常工作;服务器侦听并接受连接,当前从客户端获取文本并将其发送回。

问题是我不太确定如何处理返回 WSAEWOULDBLOCK 或有效套接字以外的其他内容的 accept() 调用。我是否只是将新套接字重置为 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* 的 std::list,而 MUDControlSocket 作为单例从 MUDSocket 派生。

如果您需要更多信息,请告诉我,并感谢您的帮助。

4

3 回答 3

0

返回错误并让调用代码适当地处理它。

于 2011-03-28T22:42:04.533 回答
0

接受可能出现的其他一些错误是内存不足、连接数已用尽等。

也许它可以通过关闭未使用或被遗忘的连接来处理,或者简单地放弃并抛出异常。

于 2011-03-28T22:43:19.043 回答
0

首先:不要将套接字设置为 0:对于某些 *NIX 系统上的套接字来说,这是一个有效的 fd,并且是一个不好的习惯。假设唯一无效的套接字 fd 是 -1。以后做任何其他事情都会在实际软件中给您带来真正的错误(相信我:我是根据调试使用 0 作为无效套接字 fd 的代码的经验说的)。

除此之外,我想说只是引发一个异常:accept除非你用完资源,否则不应该失败,这应该是异常和错误。C++ 有一种处理此类事情的机制,那就是异常。

顺便说一句:delete this几乎总是一个非常糟糕的主意,在代码中间退出可能会使调试变得困难(而不是抛出异常)并让调用者在需要时执行退出)而不是尝试接受套接字withaccept你可以select用来告诉你是否有什么可以接受的 - 并将特殊情况处理移出函数以仅在其中选择。你可以更进一步,实现一个专门的观察​​者模式(就像我一个月前在我的播客上所做的那样),不仅可以练习你的网络代码,还可以练习你的设计模式。这也将有助于使您的代码更具可移植性,并且以后可重用。

高温高压

于 2011-03-29T02:17:10.110 回答