(予約ポートの明確な舵取りしてください)別のを試してみてください、これは実際にはかなり不快な問題や不快の問題さえペアです。ファイアウォールの構成によっては、通常、要求が出されたときにIPエンドポイント上の別のエンドポイントからの応答が許可されます。だから友人がrecvfrom()
システムコールのようなものを使ってUDPデータグラムを受信すると、addressパラメータは応答する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アドレスと、それが使用することを選択したポート番号になります。コードで指定するポート番号は、友人がデータを送信するポートとは完全に異なる場合があります。最終的には、ファイアウォールがまったく別のポートで送受信している可能性があるため、どのポートを使用するかは問題ではありません。これはNetwork Address Translationのすべてです。その障壁を克服するためのヒントについては、RFC3235を読むことをお勧めします。
最良のアプローチ私見さ:クライアントを持つ
- OSがゼロポート番号で
bind()
を呼び出したり、バインドを飛ばしいずれかの方法でポートを選択してみましょう全く
- がソケットからアドレス情報を受け取りますレイヤー(例:
recvfrom()
の第5引数と第6引数)
- クライアントは前の手順で取得したエンドポイントに応答を送信します
- 前の手順が完了するまでファイアウォールの設定を調整しますrk
もちろん、すべての魔法は最後のステップです。 NATを無効にしたり、ファイアウォールが決してポートを切り替えることができないようにするには、ポート番号を釘付けにしてbind
を実行することもできます。どのようなポート番号が予約されているのか、あるいは一般に使用されているのかを知るには、%WINDIR%\system32\drivers\etc\services
(またはOSの傾きに応じて/etc/services
)を見てください。