6

私にはとても奇妙に見えます。同じポートで複数の TCP サーバーを実行できます。

次のコードで Apache MINA ライブラリを使用します。

IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.bind(new InetSocketAddress(80));

ポート 80 は、別のプログラムによって既に使用されています。しかし、「アドレスは既に使用されています」という例外は発生しませんでした。netstat を使用すると、次のことがわかります。

C:\>netstat -oan |find /i "LIST"
  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       2220
  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       904
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       840

誰かが私にそのような行動を説明できますか?

OS:ウィンドウズ7。

ありがとう。

4

1 に答える 1

3

通常、TCPポート、Windows、またはその他のOS(少なくとも主要なOS)でリッスンできるプロセスは1つだけです。Windowsでは、2つのプロセスがポートを共有している場合、エラーコード10048が発生することが予想されます。プロセスが異なるインターフェイスアドレスにバインドされている場合、これは適用されません(一方がINADDR_ANY特定のアドレスにバインドされ、もう一方が特定のアドレスにバインドされている場合でも、それらは衝突しません)。SO_REUSEADDRまた、 2番目のソケットに設定されている場合、これは適用されません。

ただし、両方のプロセスがバインドされてINADDR_ANYおり、プロセスが設定されていないと主張しているためSO_REUSEADDR、これはパズルです。私が知る限り、3つの可能性があります。

  1. 基になるライブラリの何かがSO_REUSEADDRデフォルトで設定されています。
  2. 2番目のソケットは実際には後で開かれ、それはを指定するものSO_REUSEADDRです。
  3. これを可能にするWindowsソケットレイヤーにバグがあります。

完璧なソフトウェアはないと思いますが、特に簡単に再現できる場合は、3番目のオプションを選択することを躊躇します。netstatプロセスを開始する前後の出力を注意深く観察し、その前に他のリスナーが存在するかどうかを確認することをお勧めします。また、他のプロセスを特定し、それが関連しているかどうかを確認してください(そのためにタスクマネージャーでPID列を有効にできます)。

編集

SO_REUSEADDR以下のコメント投稿者は、の動作がプラットフォーム間で異なることを指摘する必要があることを思い出させてくれました。Windowsでは、オプションを使用して新しいソケットを他のリスニングソケットと同じポートに強制的にバインドできます。ここで説明するように、2つのソケットが両方ともTCPの場合、動作は未定です。実際には、2番目のソケットはおそらくアドレスを「盗む」が、公式の行は動作が未定義であるように思われる。

2番目のソケットが正常にバインドされると、そのポートにバインドされたすべてのソケットの動作は不確定になります。たとえば、同じポート上のすべてのソケットがTCPサービスを提供する場合、そのポートを介した着信TCP接続要求は、正しいソケットによって処理されることが保証されません。動作は非決定的です。

Linux(および他のUnixバリアント)は、古いものがまだリッスンしている場合、2つのTCPソケットが同じポートを共有することを許可しません。この場合、SO_REUSEADDR古いソケットがTIME_WAITにある場合にのみ、新しいソケットのバインドを許可します(おそらく、FIN_WAIT状態とCLOSE_WAIT状態の場合は、それを確認する必要があります)。

余談ですが、Windowsで最初に遭遇したときの動作の違いは非常に驚くべきものでしたが、自分でテストしました。SO_REUSEADDR両方のソケットを設定すると、まったく同じアドレスとポートに同時に正常にバインドできる可能性があります。 。ただし、私の場合はそれほど重要ではなかったため、この状況での正確な動作について詳細なテストを行っていません。

どのプラットフォームが「正しい」かについては説明しませんが、確かにWindowsの動作がセキュリティの問題を引き起こしているSO_EXCLUSIVEADDRUSEため、他のソケットが強制的にバインドされないようにするオプションが考案されました。また、Windowsバージョンは完全に異なるオプションと見なされるべきであり、動作が異なり、たまたま同じ名前であるという意見もあります。

于 2013-02-02T01:23:52.257 に答える