ソケットの例外:“エンドポイントマッパーから使用できるエンドポイントはもうありません”
質問
WinsockとC ++を使用してサーバーアプリケーションをセットアップしています。私が抱えている問題は、 listen
を呼び出すと、最初の例外が発生することです。通常、これらは無視できると思います(?)が、同じ問題を抱えている他の人を見つけました。どんな助けも大歓迎です。
最初のチャンスの例外は次のとおりです。
MyApp .exeの0x * 12345678 *での最初の例外:0x000006D9:エンドポイントマッパーから使用可能なエンドポイントはもうありません。
これがソケットによって引き起こされる可能性があるという証拠を見つけましたそして、私が取り組んでいるコードは次のとおりです。例外は、下から5行目の listen
の呼び出しで発生します。
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;
}
解決
非常にビジーなサーバーでは、ソケットが不足している可能性があります。一部の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()メソッドで設定した保留中の接続の数です。
他のヒント
元の問題はwinsockとは関係ありません。上記の答えはすべて間違っています。初回の例外は無視してください。アプリケーションの問題ではなく、内部エラー処理のみです。
実際に問題が発生していますか?たとえば、未処理の例外が原因でプログラムが終了しますか?
問題がない場合でも、デバッガはメッセージを出力する場合があります。たとえば、こちら。
あー、着信接続の最大数を大幅に制限しているからでしょうか?
listen (m_accept_fd, 5)
// Limit here ^^^
より多くのバックログを許可すると、問題を処理できるはずです。 5の代わりにSOMAXCONNなどを使用します。
また、問題がサーバーの起動時のみである場合は、LINGER(SO_LINGER)をオフにして、接続がぶらぶらしてソケットをブロックしないようにすることができます...
これはあなたの質問に直接答えませんが、C ++を使用しているので、 Boost :: Asio でソケットコードを処理します。これにより、winsock APIをうまく抽象化でき、エラー状態をより簡単に診断できるようになります。