Socket Programming: UDP Client-Server in C Socket Programming: UDP Client-Server in C unix unix

Socket Programming: UDP Client-Server in C


When developing networking software (especially when using the BSD socket interface), it's important to keep things as simple as possible until you've established basic communication. Then you can incrementally add functionality, while making sure that you don't break anything along the way.

On the client side, keeping things simple means

  • Don't call bind in the client. The OS will choose an appropriate interface and assign a random port number, so there's no need to bind the socket.

  • Use a hard-coded server address (e.g. 127.0.0.1). Address 127.0.0.1 (0x7f000001) is the local host address, suitable for sending packets to a server on the same machine.

  • Use a hard-coded port number (e.g. 50037). Ephemeral port numbers should be greater than 0xC000 hex (49152 decimal).

  • Use a hard-coded message, e.g. "hello".

With that in mind, here's what the client software looks like

int main( void ){    int fd;    if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {        perror("socket failed");        return 1;    }    struct sockaddr_in serveraddr;    memset( &serveraddr, 0, sizeof(serveraddr) );    serveraddr.sin_family = AF_INET;    serveraddr.sin_port = htons( 50037 );                  serveraddr.sin_addr.s_addr = htonl( 0x7f000001 );      for ( int i = 0; i < 4; i++ ) {        if (sendto( fd, "hello", 5, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {            perror( "sendto failed" );            break;        }        printf( "message sent\n" );    }    close( fd );}

On the server side, keeping things simple means

  • Bind to INADDR_ANY, i.e. let the OS pick an appropriate interface.
  • Bind to a hard-coded port, e.g. 50037 (must be the same port the client uses).
  • Don't request the address information from recvfrom, i.e. pass NULL, 0 as the last two parameters.

With that in mind, here's what the server software looks like

int main( void ){    int fd;    if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {        perror( "socket failed" );        return 1;    }    struct sockaddr_in serveraddr;    memset( &serveraddr, 0, sizeof(serveraddr) );    serveraddr.sin_family = AF_INET;    serveraddr.sin_port = htons( 50037 );    serveraddr.sin_addr.s_addr = htonl( INADDR_ANY );    if ( bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {        perror( "bind failed" );        return 1;    }    char buffer[200];    for ( int i = 0; i < 4; i++ ) {        int length = recvfrom( fd, buffer, sizeof(buffer) - 1, 0, NULL, 0 );        if ( length < 0 ) {            perror( "recvfrom failed" );            break;        }        buffer[length] = '\0';        printf( "%d bytes: '%s'\n", length, buffer );    }    close( fd );}