简体   繁体   English

UDP客户端仅在特定情况下才会卡在recvfrom中

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM