無料のソケットポートを取得するにはどうすればよいですか? C ++

StackOverflow https://stackoverflow.com/questions/803012

  •  03-07-2019
  •  | 
  •  

質問

UDPテストクライアント/サーバーを作成していますが、ファイアウォール経由で取得したいです。おそらく、私がする必要があるのは、両方の側が正しいIPとサーバーに送信することだけです。 IPの取得は問題ではありませんが、クライアントにランダムな空きポートを選択させてユーザーに報告させるにはどうすればよいですか?最終的には仲人サーバーに接続したいと思いますが、今は簡単な作業用のプロトタイプが必要です。ポート番号を入力して、友人/テスターがIMで#を送信してテストできるようにします。

ポート番号を取得するにはどうすればよいですか? 長い説明をごめんなさい。私は、descを与えてはいけないとき、私が尋ねていることをしないように人々に言われます:(

役に立ちましたか?

解決

高度に専門的な用語を使用する場合、これは実際にはかなり厄介な問題、または2つの厄介な問題です。ファイアウォールの構成によっては、通常、リクエストの送信元としてIPエンドポイント上の別のエンドポイントからの応答が許可されます。そのため、友人が recvfrom()システムコールのようなものを使用してUDPデータグラムを受信した場合、アドレスパラメータは応答するIPエンドポイント情報を受信します。そのため、もう一方の端は、同じアドレス情報を使用して sendto()で応答できるはずです。次のようなもの:

/* initiator */
struct sockaddr_in hisaddr;
memset(&hisaddr, 0, sizeof(hisaddr));
hisaddr.sin_addr.s_addr = htonl(target_ip);
hisaddr.sin_port = htons(target_port);
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&hisaddr, sizeof(hisaddr));

/* receiver */
struct sockaddr_in peeraddr;
socklen_t peer_sz = sizeof(peeraddr);
recvfrom(sd, buf_ptr, buf_sz, 0, (struct sockaddr*)&peeraddr, &peer_sz);
/* build response */
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&peeraddr, peer_sz);

反対側の peeraddr は、あなたの外部アドレス、またはより正確には、ファイアウォールのIPアドレスと使用することを選択したポート番号になります。コードで指定するポート番号は、友人がデータを送信する必要があるポートとは完全に異なる場合があります。最終的には、ファイアウォールがまったく異なるポートで送受信している可能性があるため、使用するポートを選択しても問題ありません。これがネットワークアドレス変換がすべてです。そのハードルを克服するためのヒントについては、 RFC3235 を読むことをお勧めします。

私見の最善のアプローチは次のとおりです:

  1. OSに bind() ゼロのポート番号を使用するか、バインドを完全にスキップします
  2. クライアントにアドレス情報をソケットレイヤーから受信させる(たとえば、 recvfrom()
  3. クライアントは、前の手順で取得したエンドポイントに応答を送信します
  4. 前の手順が機能するまでファイアウォール構成を微調整します

もちろん、すべての魔法は最後のステップにあります。 NATを無効にしたり、ファイアウォールがポートを切り替えないようにできる場合は、ポート番号を特定し、 bind -ingすることもできます。 %WINDIR%\ system32 \ drivers \ etc \ services (またはOSの傾向に応じて / etc / services )を見て、次のことを理解してください。予約されているポート番号または一般的に使用されているポート番号。

他のヒント

一般的に-あなた-開発者として-ポートを選択します。設定ファイルまたはユーザー入力からポートを読み取るようにアプリケーションを設定できますが、魔法のファイアウォールはどのポートを使用するかを教えてくれません...

あなたの質問を正しく理解しているなら、あなたがプログラムで望むことをする方法があるかどうかわかりません(そして、たとえあったとしても、それが正しいアプローチだとは思いません)。サーバーマシンで使用されていないポート(および通信が双方向の場合はクライアントマシンの異なるポートまたは同じポート)を見つける必要があり、そのポートはファイアウォールを通過できる必要があると思います。 「IPの取得は問題ない」と言っているので、ファイアウォールの一部またはすべてのポートをファイアウォール内の特定のコンピューターに転送するようにファイアウォールを既に構成していると思いますか?その場合、探しているポートは転送したポートの1つです。そのポートで他のサービスが実行されていない限り、任意のサービスを選択できます。 1024未満のポートは予約されているため、おそらくそれよりも大きい番号を選択する必要があります。 nmap などの単純なポートスキャンツールを使用して、どのポートでコンピューターで実行されているサービスを確認し、別のポートを選択できます。 1。 nmap は、ソケットの作成時にファイアウォールやさまざまな bind ルールにだまされる可能性があることに注意してください。

O / Sが選択したランダムなポート番号に頼るよりも、固定ポートを選択した方が良いと思います。

ランダムなポートを使用する場合、プログラムを実行するたびにファイアウォール設定を変更する必要があります。

WINSOCKを使用している場合は、次のリンクを確認してください。 http://msdn.microsoft.com/en-us /library/aa280717(VS.60).aspx 基本的に2つの選択肢があり、ポートを0に設定し、システムがあなたに1つを割り当てるか、うまくいかない場合はランダムに選択してソケットを開くようにします(必ず予約ポートを避けてください)

データを送信する前に

bind()ソケット。 bind()にポート0を指定すると、OSは未使用のポートを選択します。その後、getsockname()を使用して、WSAが選択したポートを確認できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top