0
votes

I am trying to implement UDP sockets in C in a very simple/basic fashion. My programs are meant to send/receive files between terminals with one program running on each. I am having a problem with the sendto() function in my client code. Here is my code:

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

#define BUFFER_SIZE 512

int main(int argc, char *argv[])
{
    struct sockaddr_in client;
    int sockfd, bytes, errno, slen = sizeof(client);
    char buffer[BUFFER_SIZE];

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    if(sockfd == -1)
    {
        perror("Socket creation failed.");
        return 0;
    }

    client.sin_addr.s_addr = INADDR_ANY;
    client.sin_family = AF_INET;
    client.sin_port = htons( 0 );

    if( bind(sockfd, (struct sockaddr *)&client, sizeof(client)) == -1)
    {
        perror("Bind call failed.");
        return 0;
    }

    while(1)
    {
        printf("Enter message : ");
        fgets(buffer, BUFFER_SIZE, stdin);

        printf("Message: %s\n", buffer);
        bytes = sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&client, sizeof(client));

        printf("Bytes: %d\n", bytes);

        if(bytes == -1)
        {
            printf("Error number: %d", errno);
            perror("Send failed.");
            return 0;
        }

        memset(buffer,'\0', BUFFER_SIZE);

        if( recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &slen) == -1)
        {
            perror("Recieve failed.");
            return 0;
        }

        puts(buffer);
    }

    close(sockfd);

    return 0;   
}

No matter what I enter into the buffer, I always get error number 22 from sendto() for invalid arguments. I have tried every solution or tweak I have come across but nothing seems to work.

1
You're trying to send to port 0. That's not valid. - Barmar
You can bind to port 0, which causes a port to be automatically chosen. But you can't send to port 0. You can use getsockname after the bind to find out what port got chosen. - user2404501
When you call bind(), you're setting the local port. Port 0 means that the OS should find an unused port and bind that. - Barmar
Unrelated: there's no point in calling perror() after calling printf(), because printf() can change errno. - Barmar
You need two different sockaddr_in structures, one for binding the client address/port, another for specifying the destination address/port. - Barmar

1 Answers

2
votes

Just add this piece of code after bind()

getsockname(sockfd, (struct sockaddr *)&client, &slen);

man page

 DESCRIPTION
     The getsockname() function returns the current address for the specified
     socket.

     The address_len parameter should be initialized to indicate the amount of
     space pointed to by address.  On return it contains the actual size of
     the address returned (in bytes).

     The address is truncated if the buffer provided is too small.

RETURN VALUES
     The getsockname() function returns the value 0 if successful; otherwise
     the value -1 is returned and the global variable errno is set to indicate
     the error.