Question

I'm writing a sample of c udp socket. This is the client

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>

int
main(int argc, char *argv[]) {
    if (argc < 3) {
        fprintf(stderr, "Usage: %s ip port\n", argv[0]);
        exit(1);
    }

    int sock;
    char *server_ip;
    unsigned short server_port;
    struct sockaddr_in cliAddr, serAddr;

    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)  {
        fprintf(stderr, "socket failed\n");
        exit(1);
    }

    server_ip = argv[1];
    server_port = atoi(argv[2]);

    memset(&cliAddr, 0, sizeof(cliAddr));
    cliAddr.sin_family = AF_INET;
    cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    cliAddr.sin_port = htons(21152);

    if (bind(sock, (struct sockaddr *) &cliAddr, sizeof(struct sockaddr)) < 0) {
        fprintf(stderr, "bind failed\n");
        exit(1);
    }

    memset(&serAddr, 0, sizeof(serAddr));
    serAddr.sin_family = AF_INET;
    serAddr.sin_addr.s_addr = inet_addr(server_ip);
    serAddr.sin_port = htons(server_port);

    if (sendto(sock, "hello", 5, 0, (struct sockaddr *) (&serAddr), sizeof(serAddr)) == -1) {
        fprintf(stderr, "sendto failed\n");
        exit(1);
    }

    printf("send success\n");

    int n;
    char recvstr[50];
    if ((n = recvfrom(sock, &recvstr, 50, 0, NULL, NULL)) < 0) {
        fprintf(stderr, "recvfrom failed\n");
        exit(1);
    }

    printf("receive success: %s\n", recvstr);
    printf("from %s:%d\n", inet_ntoa(serAddr.sin_addr), ntohs(serAddr.sin_port));

    exit(0);
  }

And this is the server

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>

int
main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s port\n", argv[0]);
        exit(1);
    }

    int sock, n;
    struct sockaddr_in servaddr, cliaddr;
    char recvstr[50];
    socklen_t cliaddrlen;

    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        fprintf(stderr, "socket failed\n");
        exit(1);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(atoi(argv[1]));

    if (bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        fprintf(stderr, "bind failed\n");
        exit(1);
    }

    cliaddrlen = sizeof(cliaddr);
    if ((n = recvfrom(sock, recvstr, 50, 0, (struct sockaddr *) &cliaddr, &cliaddrlen)) < 0) {
        fprintf(stderr, "recvfrom failed\n");
        exit(1);
    }

    printf("client ip: %s, client port: %d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));

    if (sendto(sock, "hello from server", 17, 0, (struct sockaddr *) &cliaddr, cliaddrlen) == -1) {
        fprintf(stderr, "sendto failed\n");
        exit(1);
    }

    printf("send success\n");

    exit(0);
}

It works fine when client and server are in the local. Such as "./server 21151" and "./client 127.0.0.1 21151". The server will get:

client ip: 127.0.0.1, client port: 21152
send success

And the client will get:

send success
receive success: hello from serverB
from 127.0.0.1:21151

But when i change the ip to public ip.The client cannot get the response from server. The client will stop at the function recvfrom.

Any ideas?

Was it helpful?

Solution

Let me guess - you are running this on a Mac and the firewall is on? The default filtering rules will allow sending UDP out and receiving a response (the client), but will not allow to receive unsolicited datagrams on an open socket (the server).

Your code is fine otherwise, though you don't necessarily need to bind(2) the client side of the socket. The kernel will assign next available high-numbered port for the source. You might instead consider using connect(2) on the client if you plan on any extended conversation between given client and server.

You also always want to explicitly zero-terminate strings received from the network. Not doing this has been the source of endless remote exploits.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top