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

まず、ソケットを 0 に設定しないでください。これは、一部の *NIX システムのソケットに対して有効な fd であり、悪い習慣です。唯一の無効なソケット fd が -1 であると仮定します。他のことをすると、後で実際のソフトウェアに実際のバグが発生します(信頼してください:0を無効なソケットfdとして使用するコードをデバッグした経験から話しています)。

それ以外は、例外を発生させるだけだと思いますaccept。リソースが不足しない限り失敗しないはずです。これは例外的であり、エラーでもあるはずです。C++ にはそのようなことを処理するメカニズムがあり、それは例外です。

ところで:delete thisほとんどの場合、コードの途中で終了すると、デバッグが難しくなり(代わりに例外をスローし、必要に応じて呼び出し元に終了させる)、ソケットを受け入れようとする代わりに、非常に悪い考えです。をaccept使用selectして、受け入れるものがあるかどうかを伝えることができます。また、特殊なケースの処理を関数から移動して、そこでのみ選択することができます。もう少し進んで、特殊なオブザーバー パターンを実装して (約 1 か月前にポッドキャストで行ったように)、ネットワーク コードだけでなく、デザイン パターンも練習することができます。これは、コードの移植性を高め、後で再利用できるようにするのにも役立ちます。

HTH

于 2011-03-29T02:17:10.110 に答える
0

エラーを返し、呼び出し元のコードで適切に処理できるようにします。

于 2011-03-28T22:42:04.533 に答える
0

accept から発生する可能性のあるその他のエラーのいくつかは、メモリが少ない、接続数が使い果たされているなどです。

おそらく、未使用または忘れられた接続を閉じるか、単に放棄して例外をスローすることで処理できます。

于 2011-03-28T22:43:19.043 に答える