Thread: UDP socket help

  1. #1
    Registered User
    Join Date
    Jan 2011
    Posts
    41

    UDP socket help

    Hi everyone,

    I am using UDP sockets to create a simple token ring protocol for one of my classes. For this to work I need to be able to send and receive between the client programs and the server.

    What is working:
    I send to the server program from the client
    The server receives and stores the data
    The server sends data back to the client

    What isnt working:
    The client isn't receiving the data, it is just blocking on the recvfrom call.

    Any hints would be great, keep in mind this is an assignment.

    Client Code:
    Code:
    /*
       * Create a socket
       * PF_INET : Protocol Family IPv4 Internet Protocol
       * SOCK_STREAM : datagrams (connectionless, unreliable messages)
       * 0 : Only used if multiple protocols in family
       */
          socketFD = socket( PF_INET, SOCK_DGRAM, 0 ); 
          if ( socketFD < 0 )
          {
             perror( "recvUDP:socket()" );
             return -1;
          }
       
       /*
       * Get the name of this host
       */
          val = gethostname( hostname, 32 );
          if ( val < 0 ) 
          {
             perror( "recvUDP:gethostname()" );
             return -1;
          }
       
       /*
       * Get DNS information about the server
       */
          destptr = gethostbyname(argv[1]);
          if (destptr == NULL) 
          {
             perror( "recvUDP:gethostbyname()" );
             return -1;
          }
       
       /*
       * Clear all bits in srcAddrstructure
       */
          memset( &srcAddr,  0, srclen );
          memset( &destAddr, 0, srclen );
       
       /*
       * Copy server (registry) destination information into destAddr structure
       */
          destAddr.sin_family = PF_INET;
          memcpy( &destAddr.sin_addr, destptr->h_addr, destptr->h_length );
          destAddr.sin_port = htons( (u_short)atoi(argv[2]) );
       
    		
       /* create message to send to server */
          strcpy(buffer, "");
       
       
       /* send initial message to the server proram */
          sendlen = strlen(buffer) - 1;
          int bytesSent = sendto(socketFD,                   
                          buffer,                         
                          (size_t)sendlen,               
                          0,                              
                          (struct sockaddr *)&destAddr,    
                          (socklen_t)sizeof(destAddr)      
                          );
       /* error checks */
          if(bytesSent < 0)
          {
             perror( "sendUDP:sendto()" );
             return -1;
          }
          if(bytesSent < sendlen)
          {
             fprintf(stderr, "sendUDP:sendto() - short write\n");
             return -1;
          }
       
            /* close bound socket */
          close(socketFD);
          
          /* allocate a new socket */
          socketFD = socket( PF_INET, SOCK_DGRAM, 0 );
          if ( socketFD < 0 )
          {
             perror("sendUDP:socket()");
             return -1;
          }
       
       /*                                                                                                                                                        
       * Bind a name to the socket                                                                                                                                       */
          val = bind( socketFD, (struct sockaddr *)&srcAddr, (socklen_t)srclen);
          if ( val < 0 )
          {
             perror( "recvUDP:bind()" );
             return -1;
          }
       
       /*
       * Recv the data from the server registry
       * The data received will be the machine/port that this program sends to
       */
          fromlen = sizeof(from); 
          memset(buffer, 0, sizeof(buffer));
          val = recvfrom( socketFD,                         //!!!! The client sits here and does nothing
             buffer,                          
             (size_t)sizeof(buffer),          
             0,                               
             (struct sockaddr *)&from,        
             (socklen_t *)&fromlen            
             );
          printf("val: %d\n", val);
       
       /* get the client machine's information */
          fromptr = gethostbyaddr((char *)&from.sin_addr.s_addr, sizeof(from.sin_addr.s_addr), PF_INET);
          printf("Buffer: %s\n", buffer);
       /* error checks*/
          if(fromptr == NULL)
          {
             perror("recvUDP:gethostbyaddr()");
             return -1;
          }
          if ( val < 0 )
          {
             perror( "recvUDP:recvfrom" );
             return -1;
          }
       
       /* print what the client received */
          printf("Server program on [%s] says: \"%s\"\n\n", fromptr -> h_name , buffer);
    (note: the client source file is called recvUDP.c but it is supposed to send and receive)

    Thanks,
    Hunter

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    You should not open and close sockets.... just open your socket on a designated port, bind it, and leave it open. With UDP you use the same socket for sending and receiving.

    It is very likely that the host reply is arriving while you are closing and re-opening the socket to listen on.

    You also do not assign a port when you re-open the socket... and that has to be the same port you sent from because the server is going to use your return address from the sendto() call to send back to you...

    Here is the correct way to open a UDP Port... This is for windows but it's almost identical to linux code....
    Code:
    WORD InitNetwork(WORD Port)
      { WSADATA     wsadata;              // winsock startup
        TCHAR       hn[MAX_HOSTNAME];     // host name
        DWORD       hs = MAX_HOSTNAME;    // host name size
        SOCKADDR    la;                   // local address
        WORD        lp = Port;            // local port
        // Load the Winsock DLL
        if (WSAStartup(MAKEWORD(2,0),&wsadata))
          return 0;
        // initialize local socket
        hSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
        if (hSocket == INVALID_SOCKET)
          return 0;
        // initialize localhost IP  
        GetComputerName(hn,&hs);        
        if (!GetHostAddr(hn,Port,&la))// unicode version of gethostbyname()
          return 0;
        // bind on user designated Port
        if (!bind(hSocket,&la,sizeof(SOCKADDR)))
          return 0; 
        return 1; }
    From there you resolve the server IP and Port in a sockaddr struct and then use sendto() and recvfrom() to communicate.
    Last edited by CommonTater; 02-16-2011 at 05:40 PM.

  3. #3
    Registered User
    Join Date
    Jan 2011
    Posts
    41
    Thank you for the suggestion of not closing the socket. However, I know I am opening the socket correctly as the sendto() call sends a message to the server sucessfully.

    The server's hostname and port are passed to the client via the command line and that is what I am storing in the structure, I can't listen on the port that the server is already bound to, so how do I listen on the client's port?

    I know this is unclear in text.

    Any ideas would be great,
    Thanks
    Hunter

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    The code I provided is how I open udp ports on both the server and clients in my Remote Media project.

    UDP Ports are connectionless... you don't listen() and you don't connect(). Just set up your local IP and port, bind your socket then use recvfrom() and sendto()... that's it.

    The UDP process is good old fashioned simple...
    1) load the library
    2) create a socket
    3) provide a sockaddr with local ip and port
    4) bind the socket.
    5) recvfrom()
    6) sendto() ... using addr/port from recvfrom()
    7) goto step 5

    Really... that's all there is to it.

  5. #5
    Registered User
    Join Date
    Jan 2011
    Posts
    41
    Let me see if I can explain better.
    My project is to create a token ring protocol, so the client process have to sendto() the server process and the server informs the clients of where they are in the ring.

    This means that in my client processes I have to sendto() before I recvfrom(). So my problem is that I am using sendto() to let the server know what the client's ip and port are but now I dont know how to get the clients ip and port information so i can listen to the server's reply.



    Thanks,
    Hunter

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by mcmillhj View Post
    Let me see if I can explain better.
    My project is to create a token ring protocol, so the client process have to sendto() the server process and the server informs the clients of where they are in the ring.

    This means that in my client processes I have to sendto() before I recvfrom(). So my problem is that I am using sendto() to let the server know what the client's ip and port are but now I dont know how to get the clients ip and port information so i can listen to the server's reply.
    If by "listen" you mean recvfrom(), ok. However there is a listen() function in sockets that waits for a TCP connection... and you can't do that with UDP.

    To get the local IP is very easy... Just run the computer's name through gethostbyname()... this returns the IP address for you... as noted in my code sample. Now set the port you want to use (doesn't matter which one, so long as you have exclusive use of it).

    Follow the steps...
    1) Load the library
    2) Create a socket
    3) Get the local IP by passing the computer's name to gethostbyname()
    4) set the local IP and port into a sockaddr struct
    5) bind() the socket using the sockaddr
    6) LEAVE THE SOCKET ALONE!
    7) sendto() to tweak the server
    8) LEAVE THE SOCKET ALONE!
    9) recvfrom() to get the server's reply.
    10) go to step 6

    What you don't seem to be appreciating is that the server is going to use the return address you set into the socket with bind() to reply... if you disturb the socket the address is no longer valid and the packet will be dropped.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Use one socket to send and receive message (using UDP)
    By tanya9x in forum C++ Programming
    Replies: 11
    Last Post: 02-28-2010, 05:58 AM
  2. Receive a TCP message on a UDP socket?
    By Yarin in forum C++ Programming
    Replies: 5
    Last Post: 09-05-2009, 12:21 AM
  3. Can I bind a UDP socket to a port, but send to any other port?
    By trillianjedi in forum Networking/Device Communication
    Replies: 3
    Last Post: 01-25-2009, 04:27 PM
  4. read/write through udp socket
    By xErath in forum Networking/Device Communication
    Replies: 3
    Last Post: 05-22-2005, 05:43 PM
  5. problem with UDP WSAAsyncSelect socket, no callback message received???
    By hanhao in forum Networking/Device Communication
    Replies: 1
    Last Post: 03-29-2004, 11:59 AM