8.3. The sendto() API call

Each datagram that you send on a UDP socket is sent "by itself". It's not a part of a larger conversation. There is no 'connection' to make, since there isn't a continuous stream of data. It's "one message at a time."

Therefore, a sending program must send a destination address and port with each and every datagram that gets sent. The send() API doesn't give us a place to put an address or port, so a new API is necessary, sendto().

The sendto() API is found in the IBM manuals at this location: http://publib.boulder.ibm.com/pubs/html/as400/v4r5/ic2924/info/apis/sendto.htm

It tells us that the C-language prototype for sendto() looks like this:

              int sendto(int socket_descriptor,
                          char *buffer,
                          int buffer_length,
                          int flags,
                          struct sockaddr *destination_address,
                          int address_length);

Nothing terribly different or exciting about this prototype. A procedure called 'sendto', with 6 parameters. An integer, a pointer, an integer, another integer, a pointer and finally an integer. So, lets prototype this in RPG:

         D sendto          PR            10I 0 ExtProc('sendto')  
         D   sock_desc                   10I 0 Value              
         D   buffer                        *   Value              
         D   buffer_len                  10I 0 Value              
         D   flags                       10I 0 Value              
         D   destaddr                      *   Value              
         D   addrlen                     10I 0 Value              

The first four parms are identical to those used in the send() API. The only difference is that we've added a sockaddr structure to contain the address & port number of the destination. And, like every other address structure we've done, we'll need to supply a length for it.

Please, add this little gem to your SOCKET_H member.

The sendto() API is called like this:

         c                   eval      len = %size(sockaddr_in)            
         c                   alloc     len           toaddr                
         c                   eval      p_sockaddr = toaddr                 
         c                   eval      sin_family = AF_INET                
         c                   eval      sin_addr = SOME_IP                  
         c                   eval      sin_port = SOME_PORT                
         c                   eval      sin_zero = *ALLx'00'                
         c                   if        sendto(s: %addr(buf): buflen: 0:    
         c                                  toaddr: len) < 0               
         C*** error! check errno!                                            
         c                   endif