2012-05-21 125 views
4

是否有可能通过2个端口上的recvfrom接收数据?我有一个端口用于用户请求,另一个端口用于聊天消息。是否有可能绑定两个套接字,使用不同的端口并通过一个recvfrom()接收数据?UDP在多个端口上接收数据

问候

编辑 这是否代码工作?

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)); 

所以我想在两个不同的端口上接收数据。

回答

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, ...); 
    } 
} 

注意:这仅仅是一个粗糙和准备好的样本 - 真实的代码将有错误检查等。

+0

所以我需要将两个套接字绑定到我的服务器并使用例如select? – user1324258

+0

如何在使用select接收数据时获取发件人地址? – user1324258

+0

您不会使用select()接收数据,而select()会告诉您哪个套接字有数据准备好读取,然后像平常一样使用recvfrom()读取数据。 –

2

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

我之前的回答是一个错误,因为有一段时间我被我的工作代码搞糊涂了,现实生活中的工作代码是使用无端口协议(如ICMP等)。

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

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

另外,在协议和系统功能上,您可以使用两个套接字作为一个端口,或者使用两个套接字作为无端口协议(如ICMP) - 在这种情况下,每个套接字都应接收其自己的数据副本。

以上只是有趣的,不实用。

对您而言,实用的解决方案甚至不是上面提出的两个套接字之间的选择/轮询建议,而是通过内部协议设计分隔的单个套接字 - 例如,将通道标识符等内容放入数据包中,您将保存端口堆栈。

+0

这个答案仍然是错误的。单个套接字FD _cannot_接收数据发送到多个UDP端口。 – Alnitak

相关问题