Beruflich Dokumente
Kultur Dokumente
MODULE 9
References: 1. W.R. Stevens, B. Fenner, A.M. Rudoff, UNIX Network Programming, vol. 1, Chapters 8, 20-22. Discusses: Introduction to UDP socket. Advantages of UDP. UDP Echo Server/Client with detail discussions. recvfrom and sendto functions. connect function with UDP. TCP and UDP echo server using select. Types of communication. Broadcasting. Multicasting.
Introduction to UDP sockets Recall that: o UDP is connectionless, unreliable, datagram protocol o TCP is connection-oriented, reliable byte stream protocol Some popular applications using UDP: o Domain Name System (DNS). o Network File System (NFS). o Simple Network Management Protocol (SNMP). Increases in multimedia applications will see an increase in UDP usage multimedia usually implies multicasting.
well-known port
bind()
recvfrom()
sendto()
process request
sendto()
close()
recvfrom and sendto functions #include <sys/socket.h> /* returns number of bytes read if OK, -1 on error */ ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen); sockfd, buff, and nbytes are identical to the arguments for read and write: o sockfd : descriptor, o buff : pointer to buffer, and o nbytes: number of bytes to read or write. flags is set to 0. from is a pointer to datagram. the protocol address of who sent the
addrlen is the number of bytes returned to the caller (a value-result argument). Set both from and addrlen to null pointers if we do not want to read the address of the sender. These two arguments are similar to those in accept: o In recvfrom, it tells who sent the datagram. o In accept, it tells who initiated the connection. A UDP has a receive buffer placed in the buffer. each arriving datagram is
When a process calls recvfrom, the next datagram from the buffer (in FIFO ordered queue) is returned to the process. Queue has a limited size (it can be increased using SO_RCVBUF)
/* returns number of bytes written if OK, -1 on error */ ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags, const struct sockaddr *to, socklen_t addrlen); sockfd, buff, nbytes, and flags are the same as those in recvfrom. to is a pointer to socket address structure containing the protocol address of where the data is to be sent. addrlen specifies the size of this structure. These two arguments are similar to the last two arguments in connect. o In sendto, it tells where to send the datagram. o In connect, it tells whom to establish the connection. Note that writing a datagram of length 0 is OK, resulting in a datagram with a header but no data. recvfrom and sendto: o Can be used with TCP, although there is normally no reason to do so. o Return the length of the data that was read or written as the value of the function.
fputs
Steps: 1. Read the next datagram arriving at the servers port using recvfrom. 2. Sends it back using sendto. 3. Repeat from step 1). In general UDP server is iterative. Concurrent UDP server is uncommon: o The additional cost for process creation dominates the added efficiency obtained from concurrency. This function never terminates; UDP is connectionless, so there is nothing like EOF as in TCP. UDP Echo Client Steps: 1. 2. 3. 4. Read a line from standard input using fgets. Send the line to the server using sendto. Read back the servers echo using recvfrom. Print the echoed line to standard output using fputs.
#include "unp.h" int main(int argc, char **argv) { int sockfd; struct sockaddr_in servaddr; if (argc != 2) err_quit("usage: udpcli <IPaddress>"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERV_PORT); Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); sockfd = Socket(AF_INET, SOCK_DGRAM, 0); dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr)); exit(0); }
client
TCP connection
TCP connection
TCP
Our UDP client-server example is not reliable. The client will block forever in its call to recvfrom in the function dg_cli if: o A client datagram is lost. o If the client datagram is arrived at the server but the servers reply is lost. Solution: place a timeout in the clients call to recvfrom. Other problem: we cannot tell if the datagram or the server reply that has lost. Verifying Received Response Any process that knows the clients ephemeral port number could send datagrams to our client, and these will be intermixed with the normal server replies. Solution: Use recvfrom to get the IP address and the port number of the sender, and ignore any datagrams coming not from the expected server. Problem with the solution: o Client may still fail if server is multihomed.
#include "unp.h" void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) { int n; char sendline[MAXLINE], recvline[MAXLINE + 1]; socklen_t len; struct sockaddr *preply_addr; preply_addr = Malloc(servlen); while (Fgets(sendline, MAXLINE, fp) != NULL) { Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); len = servlen; n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len); if (len != servlen || memcmp(pservaddr, preply_addr, len) != 0) { printf("reply from %s (ignored)\n", Sock_ntop(preply_addr, len)); continue; } recvline[n] = 0; /* null terminate */ Fputs(recvline, stdout); } }
What happens if we start the client without the server? Client blocks forever in its call to recvfrom, waiting for server reply that will never appear. o sendto()returns OK (in UDP means that output queue is available). o When the server is not running, an ICMP port unreachable is returned later. o In this example, the error is caused by sendto(), but the error is returned later (not from the return value of the sendto()function) asynchronous. o Asynchronous errors are the errors that are reported some time after the packet was sent. Asynchronous errors are not returned for unconnected UDP sockets. o Make the socket connected to exactly one peer (use connect for a UDP socket). o If a UDP client is sending datagrams to multiple servers, and when one server is not running, a recvfrom() returns only errno, with no information of the destination server address.
server
IP
IP
data link
data link
data link
data link
recvfrom() client
IP
IP
data link
data link
data link
data link
Asynchronous errors are not returned on UDP sockets unless the socket has been connected. Can call connect for a UDP socket, but this does not result in anything like a TCP connection. o No three-way handshake. o Instead, kernel just records the IP address and the port number of the peer. Normally it is a UDP client that calls connect, not a UDP server. With a connected UDP socket three things change: 1. We can no longer specify destination IP address and port for an output operation use write or send instead of sendto.
write or send OK OK sendto that does not specify a destination OK OK sendto that specifies a destination EISCONN EISCONN OK
Type of socket TCP socket UDP socket, connected UDP socket, unconnected
EDESTADDRREQ
EDESTADDRREQ
2. 3.
Use read or recv instead of recvfrom. Asynchronous errors are returned to the process.
peer
???
UDP
Call connect again to: o Specify a new IP address and port, or o To unconnect the socket.
Performance of UDP
Calling sendto for two datagrams involves the following steps by the kernel: on unconnected UDP socket (6 steps) o Connect the socket. o Output the first datagram. o Unconnect the socket. o Connect the socket. o Output the second datagram. o Unconnect the socket. on connected UDP socket (3 steps) o Connect the socket. o Output first datagram. o Output second datagram. When the application knows it will be sending multiple datagrams to the same peer, it is more efficient to connect the socket explicitly, calling connect and then calling multiple write.
#include "unp.h" void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) { int n; char sendline[MAXLINE], recvline[MAXLINE + 1]; Connect(sockfd, (SA *) pservaddr, servlen); while (Fgets(sendline, MAXLINE, fp) != NULL) { Write(sockfd, sendline, strlen(sendline)); n = Read(sockfd, recvline, MAXLINE); recvline[n] = 0; /* null terminate */ Fputs(recvline, stdout); } }
If datagrams are sent faster than the receiver can handle, some of the datagrams will be lost. Example (from textbook): Consider modifying dg_cli function to send 2000 1400-byte UDP datagrams to server. The echo server must count the number of datagrams received but will not echo them back in this version. Server on slower machine (client on faster machine): o Server on 80386 machine, and client on SparcStation 4: o Client sent 2000 datagrams, but the server application only received 82 of these! 96% loss rate! Server on faster machine (client on slower machine) o Server on SparcStation 4 machine, and client on 80386: o Client sent 2000 datagrams, no datagrams are lost (as expected). The number of UDP datagrams that are queued by UDP for a given socket is limited by the size of that sockets receive buffer can be changed using SO_RCVBUF. o Even if increase buffer size, for server running on slow 80386, still lose most of the datagrams!
TCP and UDP Echo Server Using select Consider combining concurrent TCP echo server with iterative UDP Echo server into a single server that uses select to multiplex a TCP and UDP socket.
/* include udpservselect01 */ #include "unp.h" int main(int argc, char **argv) { int listenfd, connfd, udpfd, nready, maxfdp1; char mesg[MAXLINE]; pid_t childpid; fd_set rset; ssize_t n; socklen_t len; const int on = 1; struct sockaddr_in cliaddr, servaddr; void sig_chld(int); /*create listening TCP socket */ listenfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); Listen(listenfd, LISTENQ); /* create UDP socket */ udpfd = Socket(AF_INET, SOCK_DGRAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); Bind(udpfd, (SA *) &servaddr, sizeof(servaddr)); /* end udpservselect01 */
Page 6.21; CRICOS Number: 00301J
FD_ZERO(&rset); maxfdp1 = max(listenfd, udpfd) + 1; for ( ; ; ) { FD_SET(listenfd, &rset); FD_SET(udpfd, &rset); if ( (nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) { if (errno == EINTR) continue; /* back to for() */ else err_sys("select error"); } if (FD_ISSET(listenfd, &rset)) { len = sizeof(cliaddr); connfd = Accept(listenfd, (SA *) &cliaddr, &len); /* child process */ if ( (childpid = Fork()) == 0) { Close(listenfd); /* close listening socket */ str_echo(connfd);/* process the request */ exit(0); } Close(connfd);/* parent closes connected socket */ } if (FD_ISSET(udpfd, &rset)) { len = sizeof(cliaddr); n = Recvfrom(udpfd, mesg, MAXLINE, 0, (SA *) &cliaddr, &len); Sendto(udpfd, mesg, n, 0, (SA *) &cliaddr, len); } } } /* end udpservselect02 */
Information available to server from arriving IP datagram TCP server accept accept getsockname getsockname
From clients IP datagram Source IP address Source port number Destination IP address Destination port number
Since UDP is connectionless, the destination IP address can change for each datagram that is sent to the server. A UDP server can also receive datagrams destined for one of the hosts broadcast addresses or for a multicast address. UDP and TCP Comparison Advantages of UDP: UDP supports broadcasting and multicasting. UDP has no connection setup or teardown. Advantages of TCP: Positive acknowledgments, retransmission of lost packets, duplicate detection, and sequencing of packets reordered by the network. Windowed flow control. Slow start and congestion avoidance.
Recommendations:
UDP must be used for broadcast of multicast applications. UDP can be used for simple request-reply applications but error detection must then be built into the application. UDP should not be used for bulk data transfer (e.g., file transfer). Exceptions (with additional acknowledgment, timeout, and retransmission capability): o NFS (Network File System) uses UDP for bulk data transfer. o TFTP (Trivial File Transfer Protocol) uses UDP for bulk data transfer. Adding Reliability to a UDP Application Two additional features that are mostly used in existing request-reply UDP applications: 1) Sequence numbers so the client can verify that a reply is for the appropriate request. 2) Timeout and retransmission to handle datagrams that are discarded. Adding sequence numbers: Client prepends a sequence number to each request, and server must echo this number back to the client in the reply.
Algorithm: 1) Send a request and wait for N seconds for response. 2) If no response, resend, and wait for another N seconds. 3) Repeat for m times if still no response, beyond that, give up. Problem: RTT for a datagram on an internet vary widely. Factors affecting the RTT: Distance. Network speed. Congestion. Use Jacobsons algorithm (see textbook) to calculate the retransmission timeout (RTO), and use exponential backoff. Three possible scenarios when RTO expires: The request is lost. The reply is lost. The RTO is small. For these three scenarios, the client retransmits the request. However, when the client receives a reply, the client cannot tell to which request the reply corresponds retransmission ambiguity problem. Solution: Use Karns algorithm (see text book). Other solution: o The client prepends the current time as a timestamp to each request, in addition to the sequence number. o The server echo back both the sequence number and the timestamp.
Page 6.25; CRICOS Number: 00301J
Concurrency is applicable if the processing of the client request takes a long time. Two different types of UDP servers: 1) A UDP server that reads a client request, sends a reply, and then finished with the client. o The server forks a child, and let each child to handle a client. 2) A UDP server that exchanges multiple datagrams with the client (like in TFTP). Problem: A server is known by its well-known port. If there are several requests from several clients, the server cannot distinguish the sources of the requests. Solution: o The server creates a new socket for each client, bind an ephemeral port to that socket, and use the socket for all its replies. o The client look at the port number of the servers first reply and send subsequent datagrams for this request to that port.
Example: Server (parent): Creates a socket, binds well-known port (69), recevfrom(), blocks until a client request arrives, fork, then another recvfrom, . Server (child): Create a new socket, bind ephemeral port(2134), process clients request, exchange additional datagrams with client on new socket.
First datagram
client
fork
#include <sys/socket.h> /* both return number of bytes read or written if OK, -1 on error */ ssize_t ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags); send(int sockfd, const void *buff, size_t nbytes, int flags);
recv is similar to read, and send is similar to write. The first three arguments of the two functions (sockfd, buff, and nbytes) are the same as the first three arguments to read and write. The flag argument is either 0, or formed by logically ORing one or more of the following constants.
flags
description
recv
send
MSG_DONTROUTE Bypass routing table lookup MSG_DONTWAIT MSG_OOB MSG_PEEK MSG_WAITALL Only this operation is nonblocking Send of receive out-of-band data Peek at incoming message Wait for all data
MSG_DONTROUTE: Tells the kernel that the destination is on locally attached network and not to perform a lookup of the routing table.
MSG_DONTWAIT: specifies nonblocking for a single I/O operation, without having to turn on the nonblocking flag for socket, perform the I/O operation, and then turn off the nonblocking flag. MSG_OOB: For Out of Band Data (Chapter 21). MSG_PEEK: Let us look at the data that is available to be read, without having the system discard the data after recv or recvfrom returns. MSG_WAITALL: Tells the kernel not to return from a read operation until the requested number of bytes have been read if the system supports this flag, we do not need the readn function.
#include <sys/uio.h> /* both return number of bytes read or written if OK, -1 on error */ ssize_t ssize_t readv(int filedes, const struct iovec *iov, int iovcnt); writev(int filedes, const struct iovec *iov, int iovcnt);
These two functions are similar to read and write. readv lets us read into from one or more buffers with a single function call scatter read. writev lets us write from one or more buffers with a single function call gather write. struct iovec { void iov_base; size_t iov_len; } /*starting address of buffer */ /*size of buffer*/
# include <sys/socket.h> /* both return number of bytes read or written if OK, -1 on error */ ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);
The most general of all the I/O functions: o recvmsg read, readv, recv, recvfrom. o sendmsg write, writev, send, sendto.
Both functions package most of the arguments into a msghdr structure: struct msghdr { void msgname; /* protocol address */ socklen_t msg_namelen; /*size of protocol address*/ struct iovec msg_iov; /* scatter/gather array*/ size_t msg_iovlen; /*#elements in msg_iov*/ void msg_control; /*ancillary data*/ socklen_t msg_controllen; /*length of ancillary data*/ int msg_flags; /* flags returned by recvmsg*/ }
read, write functions: any descriptor. single read/write buffer. readv, writev functions: any descriptor. scatter/gather read/write. recv, send functions: only socket descriptor. single read/write buffer. Optional flags. recvfrom, sendto functions: only socket descriptor. single read/write buffer. Optional flags. Optional peer address.
recvmsg, sendmsg functions: only socket descriptor. Scatter/gather read/write. Optional flags. Optional peer address. Optional control information.
Types of communication Unicast (1:1) Concast (n:1) Multicast (1:n) Broadcast (1:n) Anycast Unicast (1:1)
Sender
Receiver
Point to point communication. There is exactly one sender and one receiver. Not suitable for group communication. Concast (n:1)
Several senders can send user data to a single receiver. Also called as concentration.
Page 6.33; CRICOS Number: 00301J
A single data source transmits user data to one or more receivers. In broadcast there is no restriction with respect to group of receivers. o Data is sent to all receivers simpler than multicast. o ARP uses broadcast From IP address it obtains the hardware address. o Can be used for resource discovery. Anycast The destination is a group of addresses like in multicasting. It does not deliver the packet to all of them it tries to deliver it to just one, usually the nearest one. TCP works with only unicast address a process/thread talks to only one other process/thread. Broadcasting is normally limited to a LAN.
Broadcast addresses
A broadcast address identifies all interfaces on the subnet. IPv4 address: {netid, subnetid, hostid} broadcast addresses: 4 types of
1. Subnet-directed broadcast address: {netid, subnetid, -1} o Currently the most commonly used type. o Normally routers do not forward these broadcasts. 2. All-subnet-directed broadcast address: {netid, -1, -1} o Rarely used. 3. Network-directed broadcast address: {netid, -1} o Used in a network that does not use subnetting almost nonexistent. 4. Limited broadcast address: {-1, -1, -1} o Never forwarded by a router. Broadcast address on our system: 134.7.1.255 o Use ifconfig to obtain the address. Broadcast address 255.255.255.255 is never forwarded by a router to the world!
UDP
UDP
IPv4
datalink
datalink 08:00:20:03:f6:42
Enet hdr
IPv4 hdr
UDP hdr
Dest IP = 128.7.6.5 Dest port = 7433 Dest Enet = 08:00:20:03:f6:42 Frame type = 0800
UDP
discard
IPv4
IPv4 Frame type =800 128.7.6.99=unicast 128.7.6.255=broadcast datalink 02:60:8c:2f:4e:00 Subnet 128.7.6 Enet hdr IPv4 hdr
Perfect software filtering based on IPv4 destination IP Frame type =800 Imperfect hardware filtering based on destination Enet
datalink
datalink
08:00:20:03:f6:42
UDP hdr
Dest IP = 128.7.6.255 Protocol = UDP Dest Enet = ff:ff:ff:ff:ff:ff Frame type = 0800
Page 6.37; CRICOS Number: 00301J
Fundamental problem with broadcasting: Every IPv4 host on the subnet must completely process the broadcast UDP datagram all the way up the protocol stack, through and including the UDP layer before discarding the datagram (even if the IP does not participate in the application) Every non-IP host on the subnet must also receive the entire frame at the datalink layer before discarding the frame. How to set Broadcast: Set the SO_BROADCAST socket option:
Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
Berkeley-derived kernels do not allow a broadcast datagram to be fragmented. o If the size of the datagram is larger than outgoing interface MTU EMSGSIZE is returned. o Check with Linux? o For portability, an application that needs to broadcast should limit its datagrams to 1472 bytes following the Ethernet MTU, the smallest for LAN.
#include "cc352.h" static void recvfrom_alarm(int); void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) { int n; const int on = 1; char sendline[MAXLINE], recvline[MAXLINE + 1]; socklen_t len; struct sockaddr *preply_addr; preply_addr = Malloc(servlen); Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); Signal(SIGALRM, recvfrom_alarm); while (Fgets(sendline, MAXLINE, fp) != NULL) { Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); alarm(5); for ( ; ; ) { len = servlen; n = recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len); if (n < 0) { if (errno == EINTR) // waited long enough break; // for replies else err_sys("recvfrom error"); } else { recvline[n] = 0; /* null terminate */ printf("from %s: %s", Sock_ntop_host(preply_addr, servlen), recvline); } } } } static void recvfrom_alarm(int signo) { return; /* just interrupt the recvfrom() */ }
Page 6.39; CRICOS Number: 00301J
Race condition
Multiple processes are accessing data that is shared among them, and the correct outcome depends on the execution order of the processes (non deterministic). Race conditions exist when dealing with: o Shared data (in thread programming). o Signals. Race condition with signals: o A signal can be delivered at any time. o Problem example: We use alarm signal to avoid infinite block in the recvfrom, but the alarm signal is sent when the program is blocked in sleep blocked forever in recvfrom.
alarm(1); for ( ; ; ) { len = servlen; n = recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len); if (n < 0) { if (errno == EINTR) // waited long enough break; // for replies else err_sys("recvfrom error"); } else { recvline[n] = 0; /* null terminate */ sleep(1); printf("from %s: %s", Sock_ntop_host(preply_addr, servlen), recvline); } }
Solution: o Blocking and unblocking the signal. o Blocking and unblocking the signal with pselect. o Using sigsetjmp and siglongjmp. o Using IPC from signal handler to function.
Blocking and unblocking the signal If a signal is generated while the signal is blocked kernel will not deliver the signal until the signal is unblocked. Block the signal from being delivered when not in the recvfrom. o Initialization: sigset_t sigset_alrm;
Sigprocmask(SIG_UNBLOCK, &sigset_alrm, NULL); n = recvfrom ( ); Sigprocmask(SIG_BLOCK, &sigset_alrm, NULL); Problem: unblocking of signal, call to recvfrom, and blocking the signal can NOT be an atomic operation they are independent system calls. o The solution reduces the chances problem to occur not completely eliminate the problem. o Example: signal is delivered after the last data is received by the recvfrom blocked forever in recvfrom.
Page 6.41; CRICOS Number: 00301J
#include <sys/select.h> #include <signal.h> #include <time.h> // returns: count of ready descriptors, 0 on timeout, -1 on error int pselect(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timespec *timeout, const sigset_t *sigmask); Posix.1g standard; changes from select() function are: o pselect uses timespec structure (Posix.1b realtime standard) instead of timeval structure. struct timespec { time_t tv_sec; //seconds long tv_nsec; //nano seconds }
o pselect has one additional argument: a pointer to a
signal mask. In pselect, setting of signal mask, testing of descriptors, and resetting of the signal mask are atomic operations with regard to the calling process.
Example:
sigset_t
sigset_alrm, sigset_empty;
FD_ZERO(sockfd, &rset); Sigemptyset(&sigset_alrm); Sigemptyset(&sigset_empty); Sigaddset(&sigset_alrm, SIGALRM); Signal(SIGALRM, recevfrom_alarm); Sigprocmask(SIG_BLOCK, &sigset_alrm, NULL); alarm(5); for(;;) { FD_SET(sockfd, &rset); n = pselect(sockfd+1, &rset, NULL, NULL, NULL, &sigset_empty); if (n < 0) { if (errno == EINTR) break; else ERROR } n = recvfrom( ); }
Multicasting
The benefit of multicasting over broadcasting: o Reduce the load on all the hosts not interested in the multicast packets. Multicast address identifies a set of interfaces. A multicast datagram should be received only by the interfaces that are interested in the datagram. Multicasting can be used on a LAN or a WAN. IPv6 supports only multicasting (not broadcasting). Multicasting Addresses Class D addresses are the multicast addresses in IPv4. o Range: 224.0.0.0 through 239.255.255.255 o Multicast group ID: the low order 28 bits o Group address: the 32-bit address. Special IPv4 multicast addresses: o 224.0.0.1 the all host group. All multicast-capable hosts on a subnet must join this group on all multicast capable interfaces. o 224.0.0.2 the all routers group. All multicast routers on a subnet must join this group on all multicast-capable interfaces.
28-bit group ID
The higher 24 bits of Ethernet address are always 01:00:5e. The next bit is always 0. The low order bits are copied from the low order 23 bits of the multicast address. The high-order 5 bit of group address are ignored in the mapping 32 multicast addresses map to a single Ethernet address. The low order 2 bits of the first byte of the Ethernet address identify a universally administered group address.
Address Range 224.0.0.0 to 224.0.0.255 239.255.0.0 to 239.255.255.255 239.192.0.0 to 239.195.255.255 224.0.1.0 to 238.255.255.255
The TTL field in the IP header has been used as a multicast scope field. Address scope how far the message can go before a router blocks it.
UDP
UDP
IPv4
IPv4
datalink
datalink 02:60:8c:2f:4e:00
datalink 08:00:20:03:f6:42
Enet hdr
IPv4 hdr
UDP hdr
Dest IP = 224.0.1.1 Protocol = UDP Dest Enet = 01:00:5e:00:01:01 Frame type = 0800
Page 6.47; CRICOS Number: 00301J
Multicasting on a WAN
Join group H1
sender
MR1
Multicast packet
MR5
MR2
MR3
MR4
H2
H3
H4
H5
Two other alternatives on multicasting on WAN: o Broadcast flooding packet will be broadcasted by the sender, and each MR will broadcast the packet. o Sending individual copy to each receiver.
Datatype
struct ip_mreq
Join a multicast group Leave a multicast group Specify default interface for outgoing multicasts Specify TTL for outgoing multicasts Enable or loopback of multicasts disable outgoing
Description
IP_MULTICAST_LOOP
u_char
IP_ADD_MEMBERSHIP struct ip_mreq { struct in_addr imr_multiaddr; //IPv4 class D addr struct in_addr imr_interface; // IPv4 addr of local interface } Joint a multicast group on a specified local interface. o A local interface is specified with one of its unicast addresses for IPv4. o If local interface is specified as wildcard address (INADDR_ANY), the local interface is chosen by the kernel. o Used by the receiver. A host belongs to a given multicast group on a given interface if one or more processes currently belongs to that group on that interface. More than one join is allowed on a given socket with the following conditions: o Each join must be for a different multicast address. o Each join may be for the same multicast address, but on different interface from previous joins for that address on this socket. for multihomed host. IP_DROP_MEMBERSHIP Leave a multicast group on a specified local interface. When the socket is closed, the membership is dropped automatically.
Page 6.50; CRICOS Number: 00301J
If none of the options is specified before sneding a multicast datagram: o The outgoing interface will be chosen by the kernel. o The TTL will be 1. o A copy will be looped back. IP_MULTICAST_IF Specify the interface for outgoing multicast datagrams sent on this socket. IP_MULTICAST_TTL Set the IPv4 TTL local subnet. IP_MULTICAST_LOOP Enable or disable local loopback of multicast datagrams. o Default: Enable similar to broadcast; a copy of each multicast datagram sent by a process on the host will also be looped back. default is 1, restricts the datagram to
#include "cc352.h" void getTime(int sockfd); #define MCAST_GROUP "224.0.0.7" int main(int argc, char **argv) { int sockfd, port = SERV_UDP_PORT; socklen_t len; struct sockaddr_in servaddr; char addr[MAXLINE+1]; struct ip_mreq mreq; len = sizeof(SA); if (argc > 3) err_quit("usage: %s [IP-multicast-address] [bind port #]\n", argv[0]); if (argc == 1) sprintf(addr, "%s", MCAST_GROUP);// default addr else if (argc >= 2) { snprintf(addr, MAXLINE, "%s", argv[1]); if (argc == 3) { if (sscanf(argv[2], "%d", &port) != 1) err_quit("invalid port #"); } } printf("Join multicast group: %s\n", addr); sockfd = Socket(AF_INET, SOCK_DGRAM, 0); //destination address for sendto bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; Inet_pton(AF_INET, addr, &servaddr.sin_addr.s_addr); servaddr.sin_port = htons(port); Bind(sockfd, (SA *) &servaddr, len); //set to join the multicast group Inet_pton(AF_INET, addr, &mreq.imr_multiaddr); mreq.imr_interface.s_addr = INADDR_ANY; if(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) err_quit("setsockopt fails"); for (;;) getTime(sockfd); exit(0); }
Page 6.52; CRICOS Number: 00301J
void getTime(int sockfd) { int n; time_t ticks; char line[MAXLINE + 1]; struct sockaddr reply_addr; struct utsname myname; socklen_t len = sizeof(SA); n = Recvfrom(sockfd, line, MAXLINE, 0, &reply_addr, &len); line[n] = 0; printf("Client message: %s\n", line); ticks = time(NULL); snprintf(line, sizeof(line), "%.24s\r\n",ctime(&ticks)); if (uname(&myname) < 0) err_sys("uname error"); Sendto(sockfd, line, strlen(line), 0, &reply_addr, len); }
#include "cc352.h" const static char *message = "What time is it?"; static void timeout(); #define MCAST_GROUP "224.0.0.7" int main(int argc, char **argv) { char line[MAXLINE], addr[MAXLINE+1]; int n, sockfd, on = 1; socklen_t len = sizeof(SA); struct sockaddr_in replyAdd; struct sockaddr_in mcastaddr; int port = SERV_UDP_PORT; int noOfReply = 0; struct ip_mreq mreq; if (argc > 3) err_quit("usage: %s [IP-multicast-address] [port #]\n", argv[0]); if (argc == 1) sprintf(addr, "%s", MCAST_GROUP);//default addr else if (argc >= 2) { snprintf(addr, MAXLINE, "%s", argv[1]); if (argc == 3) { if (sscanf(argv[2], "%d", &port) != 1) err_quit("invalid port #"); } } sockfd = Socket(AF_INET, SOCK_DGRAM, 0); printf("Send to servers in multicast group: %s:%d\n", addr, port); //set to join the multicast group Inet_pton(AF_INET, addr, &mreq.imr_multiaddr); mreq.imr_interface.s_addr = INADDR_ANY; if(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) err_quit("setsockopt fails");
//destination address for sendto bzero(&mcastaddr, sizeof(mcastaddr)); mcastaddr.sin_family = AF_INET; Inet_pton(AF_INET, addr, &mcastaddr.sin_addr.s_addr); mcastaddr.sin_port = htons(port); // send to this message to sthiservers in multicast group Sendto(sockfd, message, strlen(message), 0, (SA *) &mcastaddr, len); Signal(SIGALRM, timeout); alarm(2); while (1) { if((n = recvfrom(sockfd,line,MAXLINE,0, (SA *)&replyAdd, &len)) < 0){ if (errno == EINTR) break; else err_sys("error recvfrom"); } line[n] = 0; printf("The time on server %s:%d is: ", inet_ntop(AF_INET, &replyAdd.sin_addr, addr, sizeof(addr)), ntohs(replyAdd.sin_port)); printf("%s \n", line); noOfReply ++; alarm(2); } printf("%d Replies have been received \n", noOfReply); return 0; } static void timeout() { }