recvfrom 没有收到来自客户端的任何内容,但客户端正在发送信息
Posted
技术标签:
【中文标题】recvfrom 没有收到来自客户端的任何内容,但客户端正在发送信息【英文标题】:recvfrom does not receive anything from the client, but the client is sending the info 【发布时间】:2014-12-22 18:49:04 【问题描述】:所以我想确保我没有遗漏任何东西,并且我的脑海中的概念是清晰的。
这是我拥有的代码的一部分:
UDP_Msg mensajeRecibidoUdp;
struct sockaddr_in c_ain;
sock_udp=socket(AF_INET,SOCK_DGRAM,0);
struct sockaddr_in c_ain;
socklen_t tam_dir;
while(1)
if(recvfrom(sock_udp, &mensajeRecibidoUdp, sizeof(UDP_Msg), 0,
(struct sockaddr*) &c_ain, &tam_dir) <0)
....
问题是它等待消息到达。并且发送了消息,但是这段代码没有得到任何东西,它没有解冻。
这是一个简单的练习,并且客户端已经构建好了。它从一个文件中获取端口,然后发送一个 UDP_Message,它是一个包含几个整数和一个数组的结构(客户端已经知道 IP 和端口)。
我认为我处理缓冲区的方式可能是错误的,但我看到的每个示例都这样使用它。我还认为可能需要初始化 c_ain 变量,但如果我理解正确,情况并非如此。所以我不明白为什么进程会被阻塞,不知道什么是正确的词,并且由于很多时间过去了,警报响起并且进程被杀死(因为它应该有信息并保持代码,但它没有)。
我可以添加很多其他信息,我尽量保持简短。我知道调用是一个不能正常工作的调用,因为它在我运行客户端-服务器事物时的行为方式。
编辑:绑定:
bzero((char*)&dir_udp_serv,sizeof(struct sockaddr_in));
dir_udp_serv.sin_family=AF_INET;
dir_udp_serv.sin_addr.s_addr=inet_addr(HOST_SERVIDOR);
dir_udp_serv.sin_port=0;
fprintf(stderr,"SERVIDOR: Asignacion del puerto servidor: ");
if(bind(sock_udp,
(struct sockaddr*)&dir_udp_serv,
sizeof(struct sockaddr_in))<0)
fprintf(stderr,"ERROR\n");
close(sock_udp); exit(1);
第二次编辑:我刚刚意识到我在代码中有两个绑定。这个想法是我在同一台服务器上创建两个连接,一个用于 UDP,一个用于 TCP。所以我对 UDP 和 TCP 都做了同样的步骤。从我得到的答案中,我意识到这可能是错误的。即使我创建两个套接字,一个用于 UDp,一个用于 TCP,每个套接字是否只有 1 个绑定?
上面好像不是这样的。
另外,我不知道我应该添加什么更多细节,但是服务器和客户端都在同一台计算机上,所以它们的地址都是 127.0.0.1,但这是意料之中的,我相信这不会改变任何原因服务器没有得到客户端发送的信息。
【问题讨论】:
【参考方案1】:问问自己:您的客户在哪个端口发送消息?服务器代码中的那个端口在哪里? 无处。您忘记将本地套接字绑定到本地地址(和端口):
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_addr.s_addr = inet_addr("0.0.0.0");
local.sin_port = htons(PORT); // Now the server will listen on PORT.
if(bind(sock_udp, (struct sockaddr*)&local, sizeof(local)) < 0)
perror("bind");
exit(1);
// Now you may call recvfrom on your socket : your server is truly listening.
请注意,您只需要绑定一次。无需将其置于循环中。
【讨论】:
正如我所说,我没有编写所有代码,因为我认为这会很烦人,后来我意识到绑定很重要。我确实在代码中有它,这就是我所拥有的,我认为它非常相似,我将它添加到主帖中,因为 cmets 不能容纳这么多字符好吗? @keont 但你绑定到端口 0,这意味着(AFAICR)内核将选择一个 random 端口。根据这个答案,您确实需要选择一个特定的端口。 使用INADDR_ANY
宏比使用inet_addr("0.0.0.0")
更正常
@keont 这根本不是“非常相似”。您的代码绑定到 (a) 特定 IP 地址,它限制入站连接,以及 (b) 端口 0,它为您提供系统分配的端口。除非您有特殊的手动步骤来查看它是什么并相应地调整客户端,否则它不可能工作。试试 JohnWHSmith 的方法。
@EJP 好吧,想要绑定到特定的 IP 地址并不罕见,如果 OP 的 HOST_SERVIDOR
设置为 0.0.0.0
,那么它将正确绑定到所有接口。真的只是端口设置有问题。【参考方案2】:
好吧,不确定这是不是这个地方,但我自己的问题的答案是预期的:服务器正在侦听一个端口,而客户端正在发送到另一个端口。那是因为分配的端口发送给客户端的方式:在我的情况下,没有将其转换为网络格式(ntohs()),所以当客户端执行 htons() 时,数字是完全不同的。
【讨论】:
将端口发送到客户端未显示在您的代码中,只会反过来再次引发相同的问题。服务器需要知道客户端的端口号才能将自己的端口号发送给客户端。这必须在某个地方停止,并且必须对初始端口号进行编码,而不仅仅是使用端口零。 那是...我不确定您是否知道,但是如果客户端连接到您,您可以存储连接到您的信息。在 recvfrom 中,这就是第 5 个参数...您存储该信息,以便您可以随意向他发送您想要的任何内容...同样,没有人使用端口 0,当您使用 0 时,您会得到一个随机端口,即您稍后可以知道哪个是使用getsockname()。所以我的意思是,要么我不明白你在说什么,要么你没有抓住重点并在不正确的情况下对我投反对票。以上是关于recvfrom 没有收到来自客户端的任何内容,但客户端正在发送信息的主要内容,如果未能解决你的问题,请参考以下文章