UDP在多个端口上接收数据

时间:2012-05-21 14:35:57

标签: sockets udp port

是否可以通过2个端口上的recvfrom接收数据?我有一个用于用户请求的端口和另一个用于聊天消息的端口。是否可以绑定两个具有不同端口的套​​接字并使用一个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 个答案:

答案 0 :(得分:3)

不,使用单个recvfrom调用无法从两个套接字读取,因为该函数只接受单个套接字文件描述符参数。

您需要每个端口一个线程或一个机制(例如selectpoll)来告诉哪些套接字有数据等待读取。

在后一种情况下,一旦您知道哪些套接字具有待处理数据,您就可以然后在该特定套接字上调用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, ...);
     }
}

注意:这只是一个粗略的准备样本 - 真正的代码会有错误检查等。

答案 1 :(得分:2)

select / poll方法的答案适用于UDP。

我以前的回答是一个错误,因为有一段时间我对我的工作代码感到困惑,在现实生活中,这些代码与ICMP等无端口协议一起工作。

然而,回到UDP一切都取决于你是哪一方,服务器或客户端。

发送UDP数据包时,您通常会将正在使用的端口绑定到套接字,或者在使用sendto()发送数据时自动为其分配短暂端口。因此,通常以后您可以调用recvfrom()来接收回复,该回复通常会被发送回套接字的端口,该端口被绑定或分配。在这种情况下使用UDP,您可以使用单个本地套接字和单个本地端口与两个(以及更多)不同的远程地址和端口组合进行通信 - 考虑类似反向服务器: - )

此外,根据协议和系统功能,您可以为一个端口使用两个插槽,或者为ICMP等无端口协议使用两个套接字 - 在这种情况下,每个套接字都应该接收自己的数据副本。

上述内容很有趣,不实用。

对你来说,实际的解决方案甚至不是两个插座之间提出的上述选择/轮询,而是通过内部协议设计分离的单个插座 - 例如将信道标识符放入数据包中,就可以节省端口堆栈。