通常、TCPポート、Windows、またはその他のOS(少なくとも主要なOS)でリッスンできるプロセスは1つだけです。Windowsでは、2つのプロセスがポートを共有している場合、エラーコード10048が発生することが予想されます。プロセスが異なるインターフェイスアドレスにバインドされている場合、これは適用されません(一方がINADDR_ANY
特定のアドレスにバインドされ、もう一方が特定のアドレスにバインドされている場合でも、それらは衝突しません)。SO_REUSEADDR
また、 2番目のソケットに設定されている場合、これは適用されません。
ただし、両方のプロセスがバインドされてINADDR_ANY
おり、プロセスが設定されていないと主張しているためSO_REUSEADDR
、これはパズルです。私が知る限り、3つの可能性があります。
- 基になるライブラリの何かが
SO_REUSEADDR
デフォルトで設定されています。
- 2番目のソケットは実際には後で開かれ、それはを指定するもの
SO_REUSEADDR
です。
- これを可能にする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バージョンは完全に異なるオプションと見なされるべきであり、動作が異なり、たまたま同じ名前であるという意見もあります。