udp的recvfrom函数,能接收指定ip和端口发送来的数据吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了udp的recvfrom函数,能接收指定ip和端口发送来的数据吗?相关的知识,希望对你有一定的参考价值。

想写一段程序设置成,本机192.168.41.111的端口10000只接收192.168.41.110,端口号为60200发送来的数据。其他ip地址发送到本机ip,10000端口的数据不接收。部分配置如下:
int s;
struct sockaddr_in addr_GK,addr_SMP;
s = socket(AF_INET, SOCK_DGRAM, 0);

memset(&addr_GK, 0, sizeof(addr_GK));
memset(&addr_SMP, 0, sizeof(addr_SMP));

addr_GK.sin_family = AF_INET;
addr_SMP.sin_family = AF_INET;

addr_GK.sin_addr.s_addr = inet_addr("192.168.41.110");//客户端地址
addr_SMP.sin_addr.s_addr = inet_addr("192.168.41.111");//本机地址

addr_GK.sin_port = htons(60200);//客户端端口
addr_SMP.sin_port = htons(10000);//本机端口

bind(s, (struct sockaddr*)&addr_SMP, sizeof(addr_SMP));
len = sizeof(struct sockaddr);
n = recvfrom(s, buff, BUFF_LEN, 0, (struct sockaddr*)&addr_GK, &len);
程序能正常运行,但是为什么本机10000端口能接收到192.168.41.25的数据?

不能,他的参数是用来存储发送数据的socket的。
可以在接收到数据以后进行判断,如果是需要的IP则采用数据,否则丢弃数据。
参考技术A 代码没啥问题,不知道GPRS发送代码是怎样的

UDP 在多个端口上接收数据

【中文标题】UDP 在多个端口上接收数据【英文标题】:UDP receiving data on multiple ports 【发布时间】:2012-05-28 01:49:15 【问题描述】:

是否可以在 2 个端口上使用 recvfrom 接收数据?我有一个用于用户请求的端口和另一个用于聊天消息的端口。是否可以绑定两个不同端口的socket,用一个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));

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

【问题讨论】:

【参考方案1】:

不,不可能使用对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, ...);
     

注意:这只是一个粗略且现成的示例 - 真实代码会进行错误检查等。

【讨论】:

所以我需要将两个套接字绑定到我的服务器并使用例如 select? 用select接收数据时如何获取发件人地址? 您不会使用 select() 接收数据,而是 select() 会告诉您两个套接字中的哪一个已准备好读取数据,然后您可以使用 recvfrom() 读取该数据平常。 所以使用 read() 我必须使用 recvfrom() 来接收数据? @user1324258 不,您可以使用其中任何一种,但只有recvfrom 会在未绑定的套接字上为您提供客户端 IP 地址。【参考方案2】:

选择/轮询方法的答案适合 UDP。

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

但是,回到 UDP,这一切都取决于您是服务器端还是客户端。

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

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

以上只是有趣,不实用。

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

【讨论】:

这个答案还是错的。单个套接字 FD无法接收发送到多个 UDP 端口的数据。

以上是关于udp的recvfrom函数,能接收指定ip和端口发送来的数据吗?的主要内容,如果未能解决你的问题,请参考以下文章

终端通过GPRS发送UDP数据到固定IP:端口号,socket recvfrom接收不到数据,但却有返回值,如何解决

UDP 在多个端口上接收数据

网络骇客入门之UDP编程

小弟想写一个软件,能抓取本机指定端口往外发送的UDP数据包,请问怎么实现?

关于socket通信UDP协议的问题,在客户端client下创建两个套接字s、s1分别用于recvfrom()和sendto()。

recvfrom()的一次调用只能返回一个UDP包。此种说法正确吗?