担心处理对accept()的错误调用

发布于 2024-10-27 03:36:45 字数 2150 浏览 1 评论 0原文

我正在编写一个 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 派生。

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

I'm writing a MUD server for personal learning purposes and I've, happily, managed to wrap up the socket stuff up into a couple of classes and everything appears to be working correctly; the server listens for and accepts connections and currently takes text from the client and sends it right back.

The thing is I'm not quite sure what to do with a call to accept() that returns something other than WSAEWOULDBLOCK or a valid socket. Do I just reset the new socket to 0 and return, with maybe an error message saying something bad happened? This is what I'm currently doing now, with the addition of if it happens 20 times I'll shut down the server.

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 and NewSocket are of type SOCKET and declared at file scope. SocketList is a std::list of MUDSocket* and MUDControlSocket is derived from MUDSocket as a singleton.

Let me know if you need more info and thanks for any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

关于从前 2024-11-03 03:36:46

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

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

顺便说一句:删除这个几乎总是一个非常糟糕的主意,在代码中间退出可能会使调试变得困难(而是抛出异常)并让调用者在需要时退出)您可以使用 select 告诉您是否有任何内容需要接受,而不是尝试使用 accept 接受套接字 - 并将特殊情况处理移出函数只在那里选择。您可以更进一步并实现专门的观察​​者模式(就像我在 我的播客(大约一个月前)不仅可以练习您的网络代码,还可以练习您的设计模式。这也将有助于使您的代码更加可移植,并且以后可重用。

华泰

First: don't set the socket to 0: that's a valid fd for sockets on some *NIX systems, and a bad habit to take. Assume the only invalid socket fd is -1. Doing anything else will give you real bugs in real software later on (trust me: I'm speaking from experience debugging code that used 0 as an invalid socket fd).

Other than that, I'd say just raise an exception: accept shouldn't fail unless you run out of resources, which should be both exceptional and an error. C++ has a mechanism for handling such things, and that's exceptions.

BTW: delete this is almost always a very bad idea, exiting in the middle of your code may make it hard to debug (throw an exception in stead) and let the caller do the exiting if need be) and in stead of trying to accept a socket with accept you can use select to tell you whether there is anything to accept - and move the special-case handling out of the function to only select in there. You could go a bit further and implement a specialized observer pattern (like I did on my podcast about a month ago) to practice not only your networking code, but your design patterns as well. That would also help make your code more portable, and re-usable later.

HTH

苯莒 2024-11-03 03:36:46

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

Return the error and let the calling code deal with it appropriately.

黑白记忆 2024-11-03 03:36:46

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

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

Some of the other errors possible from accept is that memory is low, the number of connections is exhausted, etc., etc.

Perhaps it could be handled by closing unused or forgotten connections, or simply giving up and throwing an exception.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文