简体   繁体   中英

UDP sockets - server not receiving any data

I am trying to develop a UDP client-server program. Here's my code:

Server

int main(int argc, char *argv[]) {
    struct sockaddr_in client, server;
    int s, i=0;
    socklen_t n;
    char buf[4];
    s=socket(AF_INET,SOCK_DGRAM,0);
    server.sin_family=AF_INET;
    server.sin_port=atoi(argv[1]);
    inet_pton(AF_INET, "localhost", &(server.sin_addr));
    bind(s,(struct sockaddr *)&server,sizeof(server));
    n=sizeof(client);

    while(1) {
        recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&client, &n);
        printf("%s", buf);
    }
    close(s);
    return 0;
}

Client

int main (int argc, char *argv[]) {
    struct sockaddr_in client, server;
    int s, n;
    char buf[30];
    char temp[4];
    s=socket(AF_INET,SOCK_DGRAM,0);
    server.sin_family=AF_INET;
    server.sin_port=atoi(argv[2]);
    inet_pton(AF_INET, argv[1], &(server.sin_addr));

    n=sizeof(server);

    while(1) {
        scanf("%s", buf);
        fflush(stdin);
        sendto(s, buf, sizeof(buf), 0, (struct sockaddr *) &server, n);
    }
    close(s);
    return 0;
}

Fairly basic in nature without any error handling. Server outputs whatever the client sends.

It stopped working on my Ubuntu machine after I forgot to delete/free my dynamically allocated memory when I was testing something. It works perfectly fine on a different Linux server.

Any idea what could be causing this? Unclosed ports, memory leaks? How do I fix this?

There are issues with your approach:

  • fflush(stdin); invokes undefined behavior. If you want to read and discard the rest of the line entered by the user, use this:

     scanf("%*[^\\n]"); /* consume all remaining chars on the line, if any */ scanf("%*c"); /* consume the linefeed if any */ 
  • The client code should just send the string, possibly with a separator, but not the full buffer, parts of which are uninitialized:

     sendto(s, buf, strlen(buf), 0, (struct sockaddr *)&server, n); 
  • The server code should null terminate the buffer received from the client:

     while(1) { ssize_t nr = recvfrom(s, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&client, &n); if (nr >= 0) { buf[nr] = '\\0'; printf("%s", buf); } } 
  • Both the client and the server should handle end of file and system call failures gracefully.

First of all, as @kaylum mentioned, you need to check for errors. Beyond that, I see several problems:

  • inet_pton() does not convert a hostname to an address. Normally, you don't want to bind to a specific IP address on the server side anyway; instead, set it to INADDR_ANY . On the client side, 127.0.0.1 will work for sending to a server on the same machine.
  • You need to convert your port number to network byte order with htons() .
  • You're sending 30 bytes but your receive buffer is only 4 bytes long. It has been mentioned that you shouldn't send the whole 30-byte buffer, but that's up to you and your protocol. You just have to be able to handle whatever is being sent.
  • As others have mentioned, fflush(stdin) is incorrect; fflush() is used for flushing output, but stdin is an input file.
  • scanf("%s", buf) does not limit the input to the size of the buffer, so that might cause a problem. Use fgets() instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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