4

2 つのポートで recvfrom を使用してデータを受信することは可能ですか? ユーザーリクエストに使用するポートと、チャットメッセージ用の別のポートがあります。異なるポートで 2 つのソケットをバインドし、1 つの recvfrom() でデータを受信することは可能ですか?

よろしく

編集 このコードは機能しますか?

int socket_fd,socket_fd2;
struct sockaddr_in addr, chat_addr;

addr.sin_family = AF_INET;
addr.sin_port = htons(1234);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");

chat_addr.sin_family = AF_INET;
chat_addr.sin_port = htons(4321);
chat_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

bind(socket_fd2, (struct sockaddr *) &chat_addr, sizeof(struct sockaddr_in));
bind(socket_fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));

したがって、2 つの異なるポートでデータを受信したいと考えています。

4

2 に答える 2

3

いいえ、 への 1 回の呼び出しを使用して両方のソケットから読み取ることはできません。recvfromその関数は 1 つのソケット ファイル記述子パラメーターしかとらないためです。

ポートごとにスレッドが必要であるか、どのソケットに読み取り待ちのデータがあるかを伝えるメカニズム (selectなど) が必要です。poll

後者の場合、どのソケットに保留中のデータがあるかがわかれば、その特定のソケットを呼び出して必要なデータを取得できます。たとえば、次のようになりますrecvfrom

// set up select parameters
fd_set socks;
FD_ZERO(&socks);
FD_SET(socket_fd, &socks);
FD_SET(socket_fd2, &socks);

// find out which sockets are read - NB: it might be both!
int nsocks = max(socket_fd, socket_fd2) + 1;
if (select(nsocks, &socks, (fd_set *)0, (fd_set *)0, 0) >= 0) {
     if (FD_ISSET(socket_fd, &socks) {
          // handle socket 1
          recvfrom(socket_fd, ...);
     }
     if (FD_ISSET(socket_fd2, &socks) {
          // handle socket 2
          recvfrom(socket_fd2, ...);
     }
}

注意: これはラフで準備が整ったサンプルです。実際のコードにはエラー チェックなどがあります。

于 2012-05-21T14:40:48.007 に答える
2

select / pollメソッドの答えは、UDPに適しています。

私の以前の答えは間違いでした。しばらくの間、実際にはICMPなどのポートレスプロトコルで動作するコードで混乱していたためです。

ただし、UDPに戻ると、サーバーとクライアントのどちらの側にいるかによって異なります。

UDPパケットを送信するときは、通常、使用しているポートをソケットにバインドするか、sendto()を使用してデータを送信するとエフェメラルポートが自動的に割り当てられます。したがって、通常は後でrecvfrom()を呼び出して応答を受信できます。応答は通常、バインドまたは割り当てられているソケットのポートに返送されます。この場合、UDPを使用すると、単一のローカルソケットと単一のローカルポートを使用して、2つ(およびそれ以上)の異なるリモートアドレスとポートの組み合わせと通信できます-リバースサーバーのようなものを考えてください:-)

また、プロトコルとシステム機能に応じて、1つのポートに2つのソケットを使用するか、ICMPのようなポートレスプロトコルに2つのソケットを使用できます。この場合、各ソケットは受信したデータの独自のコピーを受信する必要があります。

上記は興味深いものであり、実用的ではありません。

あなたにとっての実用的な解決策は、2つのソケット間で上記の選択/ポーリングを提案することさえありませんが、内部プロトコル設計によって分離された単一のソケットです-たとえば、チャネル識別子のようなものをパケットに入れると、ポートスタックを節約できます。

于 2012-12-09T00:51:05.687 に答える