17

ランダムなポート番号を割り当てるときに、Windows が誤って同じ番号を使用しないように、TCP ポートを予約して後でサービスにバインドしたいと考えています。レジストリと再起動によってこれが可能であることは知っていますが、そのような手間のかかる解決策は避けたいと思います。

プロセスがポートを実際にバインド/リッスンせずに予約し、要求に応じて安全に (つまり、競合状態を回避して) ポートを別のプロセスに渡すにはどうすればよいでしょうか?

ポート番号は事前に決定する必要はありません。最初のプロセスがランダムなポート番号を取得し、それを要求プロセスに渡すことは問題ありません。

編集:私の質問がやや不十分に述べられていることが私には起こります。私が本当に望んでいるのは、動的ポート番号の割り当てをポート 0 へのバインド操作から分離することです。これは、そのポート番号の偶発的なランダム割り当てを回避するだけでなく、その間に他のプロセスが同じアドレス/ポートにバインドするのを防ぐことも意味します。別の言い方をすれば、1 つのプロセスがポート 0 へのバインド操作を開始し (使用されるポート番号をすぐに学習し)、指定された 2 番目のプロセスが後でバインド操作を完了できるようにすることです。

現時点で、私が考えることができる最も近い回避策は、最初のプロセスが address/0 にすぐにバインドし、2 番目のプロセスがそれを要求するまでバインドされたままにすることです。取得され、アドレス/ポートに明示的にバインドされます。これには 2 つの問題があります。2) 第三者が偶発的に (または故意に) ポートを乗っ取る可能性があるわずかな時間間隔があります。

バックグラウンド

なぜ私がそんなに奇妙なことをしたいのか、あなたは興味があるかもしれません. 私は ZeroMQ をいじくり回してきましたが、主な制限の 1 つは、ipc://Windows にトランスポートがないことです。ポート マッパー プロセス (RPC エンドポイント マッパー、または Erlang の epmd に似ています) はtcp://、動的ポート割り当てを伴うトランスポートを使用して回避策を実装するためのチケットにすぎないことに気づきました。ただし、ZeroMQ クライアントとサーバーは順不同で接続することが許可されているため (つまり、サーバーがバインドする前にクライアントが接続することはエラーではありません)、接続しているクライアントがどのように検出できるかを理解しようとしています。確実性の高さ — サーバーが実際にそのポートにバインドする前に、通信に使用されるポート。

4

5 に答える 5

7

@vahapt で述べたように、を使用して動的ポート範囲を変更できますnetsh

ただし、netsh を使用してアプリケーションに必要なポートを予約し、動的ポートの既定の範囲をそのままにしておくことをお勧めします。

そうするために:

  1. Server 2008/2008 R2 に、このMicrosoft ホットフィックスをインストールします。これは、Server 2012 以降では必要ありません。
  2. 予約するポートを使用しているプロセスを停止します。予約するポートの範囲に含まれるポートをプロセスが使用している場合、NETSH は次のエラーを返し、予約は失敗します。

    ファイルが別のプロセスによって使用されているため、プロセスはファイルにアクセスできません。

  3. ポートを予約するには、次の NETSH コマンドを使用します。

    netsh int <ipv4|ipv6> Add excludedportrange [protocol=]tcp|udp [startport=]<integer> [numberofports=]<integer> [[store=]active|persistent]

    たとえば、ポート 55368 ~ 55372 を UDPv6 用に予約するには、次のコマンドを使用します。

    netsh int ipv6 add excludedportrange protocol=udp startport=55368 numberofports=5

ノート:

  • デフォルトでは、ポート予約は再起動後も保持されます
  • ポートは、プロトコルのバージョン 4 または 6 のいずれかに予約できますが、両方には予約できません (つまり、ポート 60000 を TCPv4 と TCPv6 の両方に予約することはできません)。

既存のポート予約を表示または削除する方法など、詳細については、https://support.microsoft.com/en-us/kb/929851を参照してください。

于 2016-06-06T16:07:44.727 に答える
6

netshコマンドを使用すると役立つ場合があります。Windows で使用される動的ポート範囲を変更できます。
ご指摘のレジストリ修正のようなものですが、すぐに有効になります。

netsh コマンドの詳細については、http : //support.microsoft.com/kb/929851 を参照してください。

于 2011-03-10T01:27:21.370 に答える
5

編集:これは、Windows Server 2008より前のバージョン(MicrosoftサポートKB)にのみ適用されます。

'ReservedPorts'レジストリ設定はで編集できます

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters

ポートの範囲を予約するには、「4000-4010」または「xxxx-yyyy」の形式に従いますが、単一のポートを予約するには、「4000-4000」または「xxxx-xxxx」の形式を使用する必要があります。

http://support.microsoft.com/kb/812873

于 2012-02-01T21:51:37.820 に答える
2

考えられる解決策を思いついたので、ここで回答として文書化した方がよいと思いました。

プロセスは、WSADuplicateSocket への呼び出しを介してソケットを別のプロセスに渡すことができるため、調整プロセスは動的ポートにバインドし、それを特定の IPC 名に内部的に関連付けることができます。その名前に「バインド」しようとしている ZMQ サーバー プロセスが到着すると、調整プロセスはバインドされたソケットをサーバー プロセスにコピーし、それ自体のコピーを閉じます。

この解決策は、bind() の呼び出しを避けるという私の好みには対応していませんが、厳密には必要ではないかもしれません。いくつかのテストを実行する必要があります。

于 2011-03-15T01:37:27.247 に答える
0

zbeaconZeromMQ の場合、czmq または C# NetMqのモジュールを使用してサービス検出を実装できます。

于 2015-03-13T14:25:04.107 に答える