- TCP Versus UDP
- Writing a Datagram Program
- Catching the Message
- Multicasting Datagrams
- Aligning Functionality
Catching the Message
The receiver gets the message that the sender sends, and the receiver's program looks similar to the code fragment for initializing the sender. Essentially, you change the last line (note the changes in bold) and add one more:
addr.sin_port = htons(DEST_PORT); /* select the listening port*/ addr.sin_addr.s_addr = INADDR_ANY; /* accept from any network */ bind(sd, &addr, sizeof(addr)); /* set/publish the local port */
The first change tells the bind() system call to accept messages from any source. Most operating systems allow you to assign more than one network IP address. If you have more than one network address, you can designate one or all of the addresses to receive messages.
The bind() call tells the operating system that you want DEST_PORT for the receiver. This essentially publishes that port for other programs to send messages to. This is one instance when you must check the return value of bind(), because the program is most likely to fail here when setting up a socket. If the call returns anything but zero, you have some error.
The sender transmits the datagram to this port. The receiver can pick up the incoming packet with a special read call:
char buf[MAXBUF]; int len = sizeof(addr); /* wait for and read a datagram from the network */ int bytesread = recvfrom(sd, buf, bufsize, 0, &addr, &len);
When the receiver program gets to this point, it gets the message from a queue. If no message is ready, it waits until one arrives. The last two variables, addr and len, return the sender's address. You can ignore these values by setting the parameters to zero. However, you probably want to capture this information, because you need the address to reply.
As stated earlier, the maximum datagram size is 64KB. This can get a little tricky. Even though you have that much space, if the receiver doesn't provide a buffer big enough for the incoming message, the recvfrom() call truncates and loses the unread data. Also, the size is not 65535 bytes; instead, you may lose 2040 bytes for the IP header. The length encompasses the whole message, both header and data.
You may notice that these algorithms use separate programs or multitasking. This is intentional. While one program/thread waits in a recvfrom() system call, the other program/thread can send messages. You could use nonblocking I/O, but creating a separate thread or task is much easier (see Linux Socket Programming for more information). This is especially true while connected to a multicast channel.