7

winsock と C++ を使用してサーバー アプリケーションをセットアップしています。私が抱えている問題は、への呼び出しがlisten最初のチャンスの例外になることです。通常、これらは無視できると思いますが (?)、同じ問題を抱えている他の人を見つけました。アプリケーションが時々ハングする原因です。どんな助けでも大歓迎です。

最初の例外は次のとおりです。

MyApp .exeの 0x*12345678* での初回例外: 0x000006D9: エンドポイント マッパーから使用できるエンドポイントはこれ以上ありません。

これがソケットが原因である可能性があるという証拠をいくつか見つけました。私が使用しているコードは次のとおりです。例外はlisten、下から 5 行目の への呼び出しで発生します。

  m_accept_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if (m_accept_fd == INVALID_SOCKET)
  {
    return false;
  }

  int optval = 1;

  if (setsockopt (m_accept_fd, SOL_SOCKET, SO_REUSEADDR,
                  (char*)&optval, sizeof(optval)))
  {
    closesocket(m_accept_fd);
    m_accept_fd = INVALID_SOCKET;
    return false;
  }

  struct sockaddr_in  local_addr;
  local_addr.sin_family = AF_INET;
  local_addr.sin_addr.s_addr = INADDR_ANY;
  local_addr.sin_port = htons(m_port);

  if (bind(m_accept_fd, (struct sockaddr *)&local_addr,
           sizeof(struct sockaddr_in)) == SOCKET_ERROR)
  {
    closesocket(m_accept_fd);
    return false;
  }

  if (listen (m_accept_fd, 5) == SOCKET_ERROR)
  {
    closesocket(m_accept_fd);
    return false;
  }
4

5 に答える 5

6

非常にビジーなサーバーでは、ソケットが不足している可能性があります。一部の TCPIP パラメータを調整する必要がある場合があります。レジストリで次の 2 つを調整します。

HKLM\System\CurrentControlSet\Services\Tcpip\Parameters
   MaxUserPort  REG_DWORD  65534 (decimal)
   TcpTimedWaitDelay REG_DWORD 60 (decimal)

デフォルトでは、ネットワーク ポート (ソケット) を解放してから再利用できるようになるまでに数分の遅延があります。また、OS のバージョンによっては、windows が使用する範囲が数千しかありません。サーバーで、コマンド プロンプトでこれを実行します。

netstat -an

結果を確認します (ファイルにパイプするのが最も簡単です: netstat -an > netstat.txt)。Timed Wait Delay ステータスに 1025 から 5000 までの多数のポートが表示される場合、これが問題であり、上記のレジストリ エントリを使用して最大ユーザー ポートを 5000 から 65534 に調整することで解決されます。上記のレジストリ エントリを使用して遅延を調整し、ポートをより迅速にリサイクルすることもできます。

これが問題でない場合は、Listen() メソッドで設定した保留中の接続の数に問題がある可能性があります。

于 2008-11-08T04:42:39.950 に答える
3

元の問題は winsock とは関係ありません。上記の答えはすべて間違っています。最初の例外は無視してください。これはアプリケーションの問題ではなく、内部エラー処理にすぎません。

于 2009-03-13T13:26:35.920 に答える
2

たとえば、未処理の例外が原因でプログラムが終了するなど、実際に問題が発生していますか?

デバッガーは、問題がない場合でもメッセージを出力する場合があります。たとえば、ここを参照してください。

于 2008-11-08T01:25:54.900 に答える
1

うーん、もしかしたら着信接続の最大数を大幅に制限しているからでしょうか?

listen (m_accept_fd, 5)
// Limit here       ^^^

より大きなバックログを許可すれば、問題を処理できるはずです。5 の代わりに SOMAXCONN のようなものを使用します。

また、問題がサーバーの起動時にのみ発生する場合は、LINGER (SO_LINGER) をオフにして、接続がぶらぶらしてソケットをブロックするのを防ぐことができます...

于 2008-11-07T16:49:27.550 に答える
0

これはあなたの質問に直接答えるものではありませんが、C++ を使用しているので、Boost::Asioのようなものを使用してソケット コードを処理することをお勧めします。これにより、winsock API の優れた抽象化が実現し、エラー状態をより簡単に診断できるようになります。

于 2008-11-07T16:45:36.807 に答える