UDP client unable to receive data from the server

7,960

You are using the value-result arguments in recvfrom() wrong. A compiler should warn you about this very loudly. Recvfrom() will try to return a number to you in the 6th parameter, so you can not pass it a constant created with sizeof().

From the manpage:

The argument addrlen is a value-result argument, which the caller should initialize before the call to the size of the buffer associated with src_addr, and modified on return to indicate the actual size of the source address.

I changed the recvfrom() loop like this and a file was successfully sent & received.

int serv_addr_size = sizeof(address);
while((cont=recvfrom(create_socket, buffer, 10, 0,(struct sockaddr *) &address,&serv_addr_size))>0) 
{
    write(1, buffer, cont);
}

Since you are calling connect() on the socket, you could also use recv(), like so:

recv(create_socket, buffer, 10, 0)

As some general advice, allways carefully check the return values from system and library calls (except maybe for printf()) and be prepared for all cases listed on the functions man-page under "return values".

EDIT The server side makes a similar error in the other direction. A parameter of sendto() that should just be the length of the passed struct, is passed as a pointer.

sendto(create_socket,buffer,cont,0,(struct sockaddr *) &client,&client_address_size);

Should be

sendto(create_socket,buffer,cont,0,(struct sockaddr *) &client,client_address_size);
Share:
7,960
Zax
Author by

Zax

Updated on November 23, 2022

Comments

  • Zax
    Zax about 1 hour

    I have a UDP client and a UDP server. The flow of the program is: first the server is executed from the terminal, the terminal creates a socket and binds it and waits for a filename from the client. In another terminal the client is executed. Here also a socket is created, and a connection is established with the server. Then a filename is provided to the client. This filename is sent to the server using sendto() function. The server is able to receive filename from the client and the server is also sending the data in the file to the client. However the receiver on the other side keeps waiting for the data from the server.

    The code for the UDP client and server is as shown below.

    UDP Server:

    #include<sys/types.h>
    #include<sys/socket.h>
    #include<netinet/in.h>
    #include<sys/stat.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<stdio.h>
    #include<fcntl.h>
    int main()
    {
        int cont,create_socket,new_socket,addrlen,fd;
        int bufsize = 1024;
        int nameLen=0;
        int client_address_size=0;
        char *buffer = malloc(10);
        char fname[256];
        struct sockaddr_in address,client;
    
        if ((create_socket = socket(AF_INET,SOCK_DGRAM,0)) > 0)
        printf("The socket was created\n");
    
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = INADDR_ANY;
        address.sin_port = htons(15000);
    
        if (bind(create_socket,(struct sockaddr *)&address,sizeof(address))== 0)
            printf("Binding Socket\n");
    
        nameLen=sizeof(address);
    
        if (getsockname(create_socket,(struct sockaddr *)&address,&nameLen)<0)
        {
            printf("\n\ngetsockname() error\n");
            exit(3);
        }
    
        printf("Port assigned is %d\n", ntohs(address.sin_port));
    
        client_address_size=sizeof(client);
    
        if(recvfrom(create_socket,fname, 255,0,(struct sockaddr *) &client,&client_address_size)<0)
        {
            printf("\n\nrecvfrom() failed\n");
            exit(4);
        }
    
        printf("A request for filename %s Received..\n", fname);
    
        if ((fd=open(fname, O_RDONLY))<0)
        {
            perror("File Open Failed");
            exit(0);
        }
    
        while((cont=read(fd, buffer, 10))>0) 
        {
            //sleep(1);
            sendto(create_socket,buffer,cont,0,(struct sockaddr *) &client,&client_address_size);
            printf("\n\nPacket sent\n");
        }
    
        printf("Request Completed\n");
    
        return close(create_socket);
    }
    

    UDP Client:

    #include<sys/socket.h>
    #include<sys/types.h>
    #include<netinet/in.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<stdio.h>
    
    int main()
    {
        int create_socket,cont;
        char *arg="127.0.0.1";
        int bufsize = 1024;
        int server_address_size=0;
        char *buffer = malloc(10);
        char fname[256];
        struct sockaddr_in address,server;
    
        if ((create_socket = socket(AF_INET,SOCK_DGRAM,0)) > 0)
            printf("The Socket was created\n");
    
        address.sin_family = AF_INET;
        address.sin_port = htons(15000);
        address.sin_addr.s_addr=inet_addr(arg);
    
        if (connect(create_socket,(struct sockaddr *) &address,sizeof(address)) == 0)
            printf("The connection was accepted with the server %s...\n",arg);
    
        printf("Enter The Filename to Request : ");
        scanf("%s",fname);
        sendto(create_socket, fname, sizeof(fname), 0,(struct sockaddr *) &address,sizeof(address));
        printf("Request Accepted... Receiving File...\n\n");
    
        server_address_size=sizeof(server);
    
    
        printf("The contents of file are...\n\n");
    
        while((cont=recvfrom(create_socket, buffer, 10, 0,(struct sockaddr *) &address,sizeof(address)))>0) 
        {
            write(1, buffer, cont);
        }
    
        printf("\nEOF\n");
        return close(create_socket);
    }
    

    Where am i going wrong? Please provide a proper solution for the same.

    Thanks in advance.

    • user207421
      user207421 over 9 years
      Very poor code. Instead of printing what happens in the success cases and ignoring the failure cases, you would be a lot better advised to check the failure cases and print errno or strerror or call perror(), so that you know about the failures. At present anything at all could be going wrong and you would never know. Printing things like 'request accepted' when what you have actually done is sent something, or 'connection accepted' when all you've done is created a connectionless socket, is equally senseless.
    • alk
      alk over 9 years
      Also compile with all waring on, and fix the code then.
    • LSerni
      LSerni about 8 years
      Have you tried capturing the data traffic with e.g. ngrep in the two cases? With a near certainty, some header is missing/badly formatted, and this way you could see which one.
    • user1050619
      user1050619 about 8 years
      @Iserni..Thanks...How can I capture the request using ngrep?
    • LSerni
      LSerni about 8 years
      With tshark: tshark -i YOUR_ETH_DEVICE -d tcp.port==80,http -Y 'http.request or http.response'; with ngrep: ngrep -d YOUR_ETH_DEVICE "GET" port 80. Remember you will not capture the whole of a large packet (you will need the full wireshark to analyze that), and of course if you do POST you must change the method verb you're looking for (here I put 'GET').
    • Thufir
      Thufir almost 5 years
      it would be useful to see working example.
  • Zax
    Zax over 9 years
    ok... i would be pleased to have some working example. Thanks in advance.
  • Zax
    Zax over 9 years
    Did you perform any modifications on the server side? Coz even after the above changes in client, i'm getting the same output. that is the client is still waiting for data to be received.
  • thuovila
    thuovila over 9 years
    Now that you mentioned it, I did remove the & operator infront of the 6th parameter in sendto(). It was an automatic reflex to the compiler warning, so I did not remember it at first. Like the other comments on your question said, the code is not very robust and you should carefully check compiler warnings.
  • Zax
    Zax over 9 years
    Thanks it worked... One more thing... after receiving all the data, the client is still waiting for more data from the server. I mean EOF is not getting printed. please clarify the same.
  • thuovila
    thuovila over 9 years
    UDP is not a connection oriented protocol. There is no marker provided by the transport, for when the data ends.
  • thuovila
    thuovila over 9 years
    So in other words, your file transfer protocol must somehow signal when the file has been transferred. I wont design that for you, but popular alternatives are 1) sending the size of the data to be transferred at the start of the transfer and then receiving while there is data left 2) scanning the received data for some special character, that means the transfer is complete.
  • Zax
    Zax over 9 years
    Yup got your point... Your second option seems to make a good option. thanks.
  • Acsor
    Acsor over 9 years
    Let me know if you found it useful!
  • Zax
    Zax over 9 years
    Thanks a lot... This has actually given a very good idea to improve my code and new idea to create a better client. One doupt i have in code is: can your code be used across 2 different machines connected via a LAN if so what changes need to be performed in your code? (Because my above code which i had posted works only for client-server within a same machine). Please do reply regarding the same.
  • Zax
    Zax over 9 years
    For the server to send the data to client , it should have the ip address on the client. How does the server get the ip address of the client?
  • Acsor
    Acsor over 9 years
    For the second question: server gets client IP address when it receives his first message (it saves client info in client struct) . Then it try to open the file (if it exists). On success, first of all it sends the file length, and then its contents. For the first one I can just say I tried my code only with my PC, but I think it is possible doing it via LAN. Don't hesitate to ask if you have still doubts.
  • Zax
    Zax over 9 years
    Thanks for the info on second question and for allowing me to ask doupts. According to the code all i have understood is inorder to initiate communication the client must know the servers IP and port, is this right? Also if possible please illustrate the first question or provide a suitable article for the same. Since i'm really new to networking field i hardly know anything. Please help regarding the same.
  • Zax
    Zax over 9 years
    The server is unable to receive filename. and hence unable to open the file. Is it because of the IP i'm using it is "127.0.0.1" what ip had you used to check the output.?
  • Acsor
    Acsor over 9 years
    UDP is connection-less, this means you don't need to use function like listen(), accept() and connect() such as with TCP. When a UDP server comes binded it is ready to receives data from every client, but it is not guaranteed that all data will arrive at their destination. This is because IP protocol (which is under UDP/TCP) doesn't guarantees any security, and neither UDP does it. I mean to say that when a client has sent his file name to the server, it stores its address to communicate with the client. In your server implementation, the only (socket) file descriptor is the server's one.
  • Acsor
    Acsor over 9 years
    For your first answer: obviously client must know the server IP and port, otherwise how could client connects to something which name isn't know?
  • Zax
    Zax over 9 years
    Hey if possible can you check this question of mine: stackoverflow.com/questions/15430540/…