[英]UDP client stucks in recvfrom only in specific situation
I'm writing a C++ code that implements an UDP server and client. 我正在编写实现UDP服务器和客户端的C ++代码。
The code works fine when I write two codes, one for the server and another for the client, as in this example : https://www.geeksforgeeks.org/udp-server-client-implementation-c/ . 当我编写两个代码时,该代码可以正常工作,一个代码用于服务器,另一个代码用于客户端,如本例所示: https : //www.geeksforgeeks.org/udp-server-client-implementation-c/ 。
What I'm trying to do is to write a client function and a server function in the same code. 我想要做的是用相同的代码编写客户端功能和服务器功能。 The ideia is that I select how the program is going to work with the command lines argument.
我的想法是选择程序如何与命令行参数一起使用。
The problem is that, implementing this way and testing in two terminals running the same code, with different command line arguments, one for server and another for client, the client stucks in the recvfrom, when receiving the server response. 问题在于,以这种方式实现并在运行相同代码的两个终端(具有一个不同的命令行参数)中进行测试,一个用于服务器,另一个用于客户端,当客户端收到服务器响应时,客户端卡在recvfrom中。
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAXLINE 1024
#define PORT 32000
int send(){
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from server";
struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr,
sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
socklen_t len;
int n;
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, ( struct sockaddr *) &cliaddr,
&len);
buffer[n] = '\0';
printf("Client : %s\n", buffer);
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &cliaddr,
len);
printf("Hello message sent.\n");
return 0;
}
int receive(){
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from client";
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int n;
socklen_t len;
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
printf("Hello message sent.\n");
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, (struct sockaddr *) &servaddr,
&len);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
return 0;
}
int main(int argc, char const *argv[]) {
int command = atoi(argv[1]);
if(command == 0){
send();
}
if(command == 1){
receive();
}
return 0;
}
The expected results is something like this, that i get when running the client and the server on separated codes: 预期的结果是这样的,我在分开的代码上运行客户端和服务器时得到的结果:
Server side: 服务器端:
Hello from client
客户您好
Hello message sent
您好消息已发送
Client side: 客户端:
Hello message sent
您好消息已发送
Hello from server
您好,服务器端
But what I get when running the code above is 但是我在运行上面的代码时得到的是
Server side: 服务器端:
Hello from client
客户您好
Hello message sent
您好消息已发送
Client side: 客户端:
Hello message sent
您好消息已发送
---gets stucked here---
---卡在这里-
What am i doing wrong? 我究竟做错了什么?
In your send()
function, you are not initializing len
to the length of the buffer where recvfrom
can store the client address. 在
send()
函数中,您没有将len
初始化为recvfrom
可以存储客户端地址的缓冲区长度。
According to the man page for recvfrom
: 根据
recvfrom
的手册页:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t recvfrom(int sockfd,void * buf,size_t len,int flags,struct sockaddr * src_addr,socklen_t * addrlen);
If src_addr is not NULL, and the underlying protocol provides the source address of the message, that source address is placed in the buffer pointed to by src_addr.
如果src_addr不为NULL,并且基础协议提供了消息的源地址,则该源地址将放置在src_addr指向的缓冲区中。 In this case, addrlen is a value-result argument.
在这种情况下,addrlen是一个值结果参数。 Before the call, it should be initialized to the size of the buffer associated with src_addr.
在调用之前,应将其初始化为与src_addr关联的缓冲区的大小。 Upon return, addrlen is updated to contain the actual size of the source address.
返回时,addrlen更新为包含源地址的实际大小。
It's not working because the client address isn't being properly received so the response message is being sent to the wrong address. 由于无法正确接收客户端地址,因此响应消息被发送到错误的地址,因此无法正常工作。 To resolve your problem, you just need to initialize
len
before the call to recvfrom
: 要解决您的问题,您只需要在调用
recvfrom
之前初始化len
即可:
socklen_t len = sizeof(cliaddr); // The size of the buffer you're passing to store the client address
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.