charles
charles

Reputation: 31

How to send UDP message to loopback address and then read from it?

I have a c program. it first tries to send UDP message to the loopback address, then read from the the loopback. But first the sendto() function fails with the message "sendto fails: Invalid argument". The code looks like:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

int main(void)
{
    struct sockaddr_in servaddr;
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&servaddr, sizeof(servaddr));

    struct in_addr addr;
    char dottedaddr[20];
    inet_aton("127.0.0.1", &addr);

        servaddr.sin_family      = AF_INET;
        servaddr.sin_addr.s_addr = addr.s_addr;
        servaddr.sin_port        = htons(0);

    struct sockaddr_in cliaddr;

        inet_aton("192.168.2.12", &addr);

        cliaddr.sin_family      = AF_INET;
        cliaddr.sin_addr.s_addr = addr.s_addr;
        cliaddr.sin_port        = htons(5000);


    if(bind(sockfd, (const struct sockaddr *)&cliaddr, sizeof(cliaddr)) == -1)
    {
        perror("bind failed");
        exit(1);
    }

    char buf[] = {'h', 'i', ' ', 'i', ' ', 'l', 'o', 'v', 'e', ' ', 'y', 'o', 'u', 0};


    if( sendto(sockfd, buf, sizeof(buf), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        perror("sendto fails");
        exit(2);
    }

    fd_set readFd;
    FD_ZERO(&readFd);
    FD_SET(sockfd, &readFd);
    struct timeval timeout;
    timeout.tv_sec = 5;
    timeout.tv_usec = 0;

    int ret = select(sockfd + 1, &readFd, NULL, NULL, &timeout);
    if(ret > 0)
    {
        if(FD_ISSET(sockfd, &readFd))
        {
            char buf2[21];
            struct sockaddr_in from;
            int len = sizeof(from);
            if(recvfrom(sockfd, buf2, sizeof(buf2), 0, (struct sockaddr *)&from, &len) == -1)
            {
                perror("recvfrom fails");
            }
        }
    }
    else if (ret == 0)
    {
        printf("select time out \n");
    }
    else
    {
        printf("select fails");
    }

}

if i change the server port from 0 to 5000, then sendto() can succeed. What is the reason ?

The second question is, after the server port is changed to 5000, the select() cannot detect the socket is readable or not. It simply timeout. I think sockfd should be readable since i just send a message to the loopback address. Is there anything wrong with the code? thank you!

Upvotes: 3

Views: 12383

Answers (1)

user2890160
user2890160

Reputation: 11

if i change the server port from 0 to 5000, then sendto() can succeed. What is the reason ?

UDP required packets to have specific source and destination port greater that zero. The only case when you can use zero port is the bind call; in that case socket will be bind on some free non-zero port and future packets from that sockets will use that number as src port.

You always should specify non-zero destination port as a param of sendto() for udp packets.

I think sockfd should be readable since i just send a message to the loopback address.

I am not sure, but it looks like you don't listen loopback. When you bind, you bind only on 192.168.2.12 network interface. You should use INADDR_ANY to bind on all interfaces, including loopback.

Upvotes: 1

Related Questions