5

HTTP サーバーとして機能するサードパーティ ライブラリがあります。アドレスとポートを渡すと、受信接続をリッスンするために使用されます。このライブラリは、バインド先のポートとアドレスを排他的に使用しないようにリッスンします。その結果、同じポートで複数回リッスンできます。

この HTTP サーバーの複数のインスタンスを同じプロセスで実行する必要があります。各インスタンスには既定のポートがありますが、そのポートが使用できない場合は、次に使用可能なポートを使用する必要があります。これが私の問題です。同じポートでリッスンする 2 つの HTTP サーバーで終わる可能性があります。

HTTP サーバーのコードを変更することはできず、指定したポートをリッスンできない場合、HTTP サーバーは警告を発しません。そのため、各 HTTP サーバーを起動する前に、ポートが既に使用されているかどうかを確認できる必要があります。SO_REUSEADDR を FALSE に設定し、SO_EXCLUSIVEADDRUSE を TRUE に設定して独自のソケットをバインドすることにより、ポートが既にリッスンされているかどうかを確認しようとしましたが、既存の HTTP サーバーが既にそのポートでリッスンしている場合、バインド呼び出しとリッスン呼び出しの両方が成功します。

この HTTP サーバーはどのようにこの効果を達成していますか? また、ポートがこの方法でリッスンされているかどうかを正確に確認するにはどうすればよいですか?

4

3 に答える 3

6

手っ取り早い方法はconnect()、ローカルホストのポートにアクセスしようとすることです。呼び出しが成功した場合はconnect()、ポートが現在リッスンされていることがわかります(接続を受信した人)。接続呼び出しが失敗した場合(特にでECONNREFUSED)、そのポートで誰もリッスンしていないことを確信できます。

もちろん、ここには競合状態があります。上記のテストを実行した直後、ただし自分でポートにバインドする前に、別のプログラムが急降下してポートを取得するのを実際に阻止するものはありません。したがって、テストの結果を絶対的なルールというよりもヒントとしてとらえ、後でポートが使用中であることがわかった場合に、(うまくいけば)何らかの方法でテストの結果を処理する必要があります。

于 2012-06-05T22:57:40.773 に答える
3

ポート番号 0 を使用します。OS が空いているポートを選択します。

于 2012-06-05T22:21:25.503 に答える
1

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspxは、さまざまなオプションがどのように相互作用するかを説明しています。

あなたはあなたのユースケースで何が起こっているのかを正確に伝えるのに十分な情報を私たちに提供していませんが、私はあなたが見ているもののように見える任意のユースケースを1つ処理できます。

Win 2003以降を使用していて、プライマリNICが10.0.0.1であり、すべてが同じユーザーアカウントで実行されているとします。

アプリの最初のインスタンスが起動し、テストコードが10.0.0.1:12345をSO_EXCLUSIVEADDREUSEにバインドしようとします。もちろん、これは機能します。

ソケットを閉じてから、HTTPサーバーにポート12345をリッスンするように指示します。これは0.0.0.0:12345をSO_REUSEADDRにバインドします。これはもちろん機能します。

これで、アプリの2番目のインスタンスが起動し、テストコードが10.0.0.1:12345をSO_EXCLUSIVEADDREUSEにバインドしようとします。MSDNの記事のチャートによると、それは機能します。

ソケットを閉じてから、HTTPサーバーにポート12345をリッスンするように指示します。これは0.0.0.0:12345をSO_REUSEADDRにバインドします。これは機能します。

これが問題である場合、HTTPサーバーに特定のアドレスをバインドさせることができないと仮定すると、テストコードで0.0.0.0を使用することで問題を解決できます。(もちろん、それが他の何百もの考えられる問題の1つである場合、その解決策は機能しません。)

HTTPサーバーが使用しているソケットオプションやアドレスなどがわからず、ソースがない場合は、デバッガーで実行して、関連する呼び出しにブレークポイントを設定します。

于 2012-06-05T23:00:55.063 に答える