next up previous
Next: About this document Up: Introduction Previous: Data Transfer

Connectionless Sockets

A datagram socket provides a connectionless communication interface. Under this model, communicationg processes need not set up a connection before they exchange messages. Instead, sender specifies a destination address in each message. There is no gurantee that the recipient will be ready to receive the message and there is no error returned if the message cannot be delivered. Messages are sent and received using the system calls sendto and recvfrom.

Datagram sockets are created as before. If a particular local address is needed, the bind operation must precede the first data transmission. Otherwise, the system will set the local address and/or port when data is first sent. To send data, the sendto primitive is used,

sendto(s, buf, buflen, flags, (struct sockaddr *)&to, tolen);
The s, buf, buflen, and flags parameters are used as before. The to and tolen values are used to indicate the address of the intended recipient of the message. When using an unreliable datagram interface, it is unlikely that any errors will be reported to the sender. When information is present locally to recognize a message that can not be delivered (for instance when a network is unreachable), the call will return 1 and the global value errno will contain an error number.

To receive messages on an unconnected datagram socket, the recvfrom primitive is provided:

recvfrom(s, buf, buflen, flags, (struct sockaddr *)&from, &fromlen);
Once again, the fromlen parameter is handled in a value-result fashion, initially containing the size of the from buffer, and modified on return to indicate the actual size of the address from which the datagram was received.

Figure 3 shows an example of a user-defined datagram-based server that echoes back messages sent by a client.

In addition to the two calls mentioned above, datagram sockets may also use the connect call to associate a socket with a specific destination address. In this case, any data sent on the socket will automatically be addressed to the connected peer, and only data received from that peer will be delivered to the user. Only one connected address is permitted for each socket at one time; a second connect will change the destination address, and a connect to a null address (family AF_UNSPEC) will disconnect. Connect requests on datagram sockets return immediately, as this simply results in the system recording the peer's address (as compared to a stream socket, where a connect request initiates establishment of an end to end connection). Accept and listen are not used with datagram sockets.

                          /* Figure 1 */
/* a client program that communicates with the UDP echo server
using Internet datagrams */

/* include files omitted */
main()
{
        struct sockaddr_in  saTo;
        int  fdTo, fromlen;
        struct servent        *pServent;
        struct hostent *pHostent;       
        char        *snd_buf;  /* must allocate memory */
        int        cch;

        /* create a socket */
        fdTo = socket(AF_INET, SOCK_DGRAM, 0);

        /* first find the address of the server */
        pServent = getservbyname("echo", "udp");

        /* find the machine address given a host name */
        pHostent = gethostbyname("s.ms.uky.edu");

        /* fill in info inthe socket address sturcture */
        bzero((char *)&saTo, sizeof(saTo));
        bcopy(pHostent->h_addr, (char *)&saTo.sin_addr,pHostent->h_length);
        saTo.sin_family = AF_INET;
        saTo.sin_port = pServent->s_port;

        /* send a message */
        cch = sendto(fdTo, tmp_buf, strlen(tmp_buf), 0, &saTo, sizeof(saTo));

        ........
}

                          /* Figure 2 */
/* Remote login server program */

main()
{
        struct sockaddr_in  from;
        int    fd, rstat;
        struct servent        *pServent;

        fdTo = socket(AF_INET, SOCK_STREAM, 0);

        pServent = getservbyname("rlogin", "tcp");

        bzero((char *)&from, sizeof(from));

        from.sin_family = AF_INET;
        from.sin_port = pServent->s_port;
        from.sin_addr.s_addr = INADDR_ANY;

        /* bind bind */
        fd(fdTo,(char *)&from, sizeof(from));

        listen(fd, 5);                /* listen to requests */
        while(1) {
            fromlen = sizeof(from);
            rstat = accept(fd, &from, &fromlen);

            /* error checking */
            /* fork off a chilld to handle this connection */
        }
}

                       /* Figure 3 */
/* An example of a simple, datagram-based echo server that echoes
   back client messages.*/
#include <stdio.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORTNUM 2005    /* user defined port, not a well-known one */

main()
{
        struct sockaddr_in  saTo;
        int  fdTo, fromlen;
        char        *req_buf;  /* must allocate memory */
        int        cch;

        fdTo = socket(AF_INET, SOCK_DGRAM, 0);

        bzero((char *)&saTo, sizeof(saTo));
        saTo.sin_family = AF_INET;
        saTo.sin_port = PORTNUM;
        saTo.sin_addr.s_addr = INADDR_ANY;

        /* bind fd */
        bind(fdTo,(char *)&saTo, sizeof(saTo));

        while(1) {        /* server loop */
            fromlen = sizeof(saTo);
            cch = recvfrom(fdTo, req_buf, 80, 0, &saTo, &fromlen);
        
            /* reply */
            sendto(fdTo, req_buf, cch, 0, &saTo, sizeof(saTo));        
        }
}

--------


next up previous
Next: About this document Up: Introduction Previous: Data Transfer



Prasun Dewan
Tue Mar 9 11:04:08 EST 2004