0 penilaian0% menganggap dokumen ini bermanfaat (0 suara)
58 tayangan9 halaman
The document discusses elementary UDP sockets. It provides an overview of how UDP differs from TCP in being connectionless and unreliable. It then shows the typical function calls used for UDP client-server communication, including sendto() to send datagrams and recvfrom() to receive them. It includes code examples of a simple iterative UDP echo server that uses recvfrom() and sendto() in a loop to continuously receive and echo back datagrams.
The document discusses elementary UDP sockets. It provides an overview of how UDP differs from TCP in being connectionless and unreliable. It then shows the typical function calls used for UDP client-server communication, including sendto() to send datagrams and recvfrom() to receive them. It includes code examples of a simple iterative UDP echo server that uses recvfrom() and sendto() in a loop to continuously receive and echo back datagrams.
The document discusses elementary UDP sockets. It provides an overview of how UDP differs from TCP in being connectionless and unreliable. It then shows the typical function calls used for UDP client-server communication, including sendto() to send datagrams and recvfrom() to receive them. It includes code examples of a simple iterative UDP echo server that uses recvfrom() and sendto() in a loop to continuously receive and echo back datagrams.
UNIT-V Elementary UDP Sockets INTRODUCTION There are some fundamental differences between applications written using TCP versus those that use UDP. These are because of the differences in the two transport layers: UDP is a connectionless, unreliable, datagram protocol, quite unlike the connection-oriented, reliable byte stream provided by TCP. Nevertheless, there are instances when it makes sense to use UDP instead of TCP. Some popular applications are built using UDP: DNS, NFS, and SNMP, for example. The below figure shows the function calls for a typical UDP client/server. The client does not establish a connection with the server. Instead, the client just sends a datagram to the server using the sendto function, which requires the address of the destination (the server) as a parameter. Similarly, the server does not accept a connection from a client. Instead, the server just calls the recvfromfunction, which waits until data arrives from some client. recvfrom returns the protocol address of the client, along with the datagram, so the server can send a response to the correct client. The figure also shows a timeline of the typical scenario that takes place for a UDPclient/server exchange. We can compare this to the typical TCP exchange. We will also describe the new functions that we us with UDP sockets, recvfrom and sendto, and redo our echo client/server to use UDP. We will also describe the use of the connect function with a UDP socket, and the concept of asynchronous errors.
send(), sendto() Send data out over a socket Prototypes #include <sys/types.h> #include <sys/socket.h> ssize_t send(int s, const void *buf, size_tlen, int flags); ssize_tsendto(int s, const void *buf, size_tlen, int flags, conststructsockaddr *to, socklen_ttolen);
Description These functions send data to a socket. Generally speaking, send() is used for TCP SOCK_STREAM connected sockets, and sendto() is used for UDP SOCK_DGRAM unconnected datagram sockets. With the unconnected sockets, you must specify the destination of a packet each time you send one, and that's why the last parameters of sendto() define where the packet is going. With both send() and sendto(), the parameter s is the socket, buf is a pointer to the data you want to send, len is the number of bytes you want to send, and flags allows you to specify more information about how the data is to be sent. Set flags to zero if you want it to be "normal" data. Here are some of the commonly used flags, but check your local send() man pages for more details: MSG_OOB Send as "out of band" data. TCP supports this, and it's a way to tell the receiving system that this data has a higher priority than the normal data. The receiver will receive the signal SIGURG and it can then receive this data without first receiving all the rest of the normal data in the queue. MSG_DONTROUTE Don't send this data over a router, just keep it local. MSG_DONTWAIT If send() would block because outbound traffic is clogged, have it return EAGAIN. This is like a "enable non-blocking just for this send." See the section on blocking for more details. MSG_NOSIGNAL If you send() to a remote host which is no longer recv()ing,you'll typically get the signal SIGPIPE. Adding this flag prevents that signal from being raised.
Return Value Returns the number of bytes actually sent, or -1 on error (and errno will be set accordingly.) Note that the number of bytes actually sent might be less than the number you asked it to send! See the section on handling partial send()s for a helper function to get around this. Also, if the socket has been closed by either side, the process calling send() will get the signal SIGPIPE. (Unless send() was called with the MSG_NOSIGNAL flag.)
Elementary UDP Sockets
Srinu Bevara Page 3
recv(), recvfrom() Receive data on a socket Prototypes #include <sys/types.h> #include <sys/socket.h> ssize_trecv(int s, void *buf, size_tlen, int flags); ssize_trecvfrom(int s, void *buf, size_tlen, int flags, structsockaddr *from, socklen_t *fromlen);
Description Once you have a socket up and connected, you can read incoming data from the remote side using the recv() (for TCP SOCK_STREAM sockets) and recvfrom() (for UDP SOCK_DGRAMsockets). Both functions take the socket descriptor s, a pointer to the buffer buf, the size (in bytes) of the buffer len, and a set of flags that control how the functions work. Additionally, the recvfrom() takes a structsockaddr*, from that will tell you where the data came from, and will fill in fromlen with the size of structsockaddr. (You must also initializefromlen to be the size of from or structsockaddr.) So what wondrous flags can you pass into this function? Here are some of them, but you should check your local man pages for more information and what is actually supported on your system. You bitwise-or these together, or just set flags to 0 if you want it to be a regular vanilla recv(). MSG_OOB Receive Out of Band data. This is how to get data that has been sent to you with the MSG_OOB flag in send(). As the receiving side, you will have had signal SIGURG raised telling you there is urgent data. In your handler for that signal, you could call recv()with this MSG_OOB flag. MSG_PEEK If you want to call recv() "just for pretend", you can call it with this flag. This will tell you what's waiting in the buffer for when you call recv() "for real" (i.e. without the MSG_PEEK flag. It's like a sneak preview into the next recv() call. MSG_WAITALL Tell recv() to not return until all the data you specified in the len parameter. It will ignore your wishes in extreme circumstances, however, like if a signal interrupts the call or if some error occurs or if the remote side closes the connection, etc. Don't be mad with it.
When you call recv(), it will block until there is some data to read. If you want to not block, set the socket to non- blocking or check with select() or poll() to see if there is incoming data before calling recv() or recvfrom(). Return Value Returns the number of bytes actually received (which might be less than you requested in the len parameter), or -1 on error (and errno will be set accordingly.) Elementary UDP Sockets
Srinu Bevara Page 4
If the remote side has closed the connection, recv() will return 0. This is the normal method for determining if the remote side has closed the connection. Normality is good, rebel! UDP Echo Server main Function
Figure 2 : Simple echo client/server using UDP 1 #include "unp.h" 2 int 3 main(intargc, char **argv) 4 { 5 intsockfd; 6 structsockaddr_inservaddr, cliaddr; 7 sockfd = Socket(AF_INET, SOCK_DGRAM, 0); 8 bzero(&servaddr, sizeof(servaddr)); 9 servaddr.sin_family = AF_INET; 10 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 11 servaddr.sin_port = htons(SERV_PORT); 12 Bind(sockfd, (SA *) &servaddr, sizeof(servaddr)); 13 dg_echo(sockfd, (SA *) &cliaddr, sizeof(cliaddr)); 14 } 712We create a UDP socket by specifying the second argument to socket as SOCK_DGRAM (a datagram socket in the IPv4 protocol). As with the TCP server example, the IPv4 address for the bind is specified as INADDR_ANY and the server's well-known port is the constant SERV_PORT from the unp.h header. 13 The function dg_echo is called to perform server processing. dg_echo Function 1 #include "unp.h" 2 void 3 dg_echo(intsockfd, SA *pcliaddr, socklen_tclilen) 4 { 5 int n; 6 socklen_tlen; 7 char mesg[MAXLINE]; 8 for ( ; ; ) { 9 len = clilen; 10 n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len); 11 Sendto(sockfd, mesg, n, 0, pcliaddr, len); 12 } 13 }
812This function is a simple loop that reads the next datagram arriving at the server's port using recvfrom and sends it back using sendto. Read datagram, echo back to sender Elementary UDP Sockets
Srinu Bevara Page 5
dg_echo function is a simple loop that reads the next datagram arriving at the servers port using recvfrom and sends it back using sendto. Despite the simplicity of this function, there are numerous details to consider, o This function never terminates, Since udp is a connectionless protocol, there is nothing like an EOF as TCp. o This function provides an iterative server There is no call to fork, so a single server process handles any and all clients. o Most TCP server are concurrent o Most UDP server are iterative
Figure 3 : TCP client/server with two clients There are two connected sockets and each of the two connected sockets on the server host has its own socket receive buffer.
Figure 4 : UDP client/server with two clients There is only one server process and it has a single socket on which it receives all arriving datagrams and sends all responses. That socket has a receive buffer into which all arriving datagrams are placed UDP Echo Client main Function 1 #include "unp.h" 2 int 3 main(intargc, char **argv) 4 { 5 intsockfd; 6 structsockaddr_inservaddr; 7 if(argc != 2) 8 err_quit("usage: udpcli<IPaddress>"); 9 bzero(&servaddr, sizeof(servaddr)); 10 servaddr.sin_family = AF_INET; 11 servaddr.sin_port = htons(SERV_PORT); Elementary UDP Sockets
Srinu Bevara Page 6
12 Inet_pton(AF_INET, argv[1], &servaddr.sin_addr); 13 sockfd = Socket(AF_INET, SOCK_DGRAM, 0); 14 dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr)); 15 exit(0); 16 } 912 An IPv4 socket address structure is filled in with the IP address and port number of the server. This structure will be passed to dg_cli, specifying where to send datagrams. 1314 A UDP socket is created and the function dg_cli is called. dg_cli Function 1 #include "unp.h" 2 void 3 dg_cli(FILE *fp, intsockfd, const SA *pservaddr, socklen_tservlen) 4 { 5 int n; 6 char sendline[MAXLINE], recvline[MAXLINE + 1]; 7 while (Fgets(sendline, MAXLINE, fp) != NULL) { 8 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); 9 n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL); 10 recvline[n] = 0; /* null terminate */ 11 Fputs(recvline, stdout); 12 } 13 } 712 There are four steps in the client processing loop: read a line from standard input using fgets, send the line to the server using sendto, read back the server's echo using recvfrom, and print the echoed line to standard output using fputs. There are four steps in the client processing loop Read a line from standard input using fgets Send the line to server using sendto Read back the servers echo using recvfrom Print the echoed line to standard output using fputs. Notice that the call to recvfrom specifies a null pointer as the ffifth and sixth arguments, this tells the kernel that we are not interested in knowing who send the reply Lost Datagrams Our UDP client/server example is not reliable. If a client datagram is lost (say it is discarded by some router between the client and server), the client will block forever in its call to recvfrom in the function dg_cli, waiting for a server reply that will never arrive. Similarly, if the client datagram arrives at the server but the server's reply is lost, the client will again block forever in its call to recvfrom. A typical way to prevent this is to place a timeout on the client's call to recvfrom. Just placing a timeout on the recvfrom is not the entire solution. For example, if we do time out, we cannot tell whether our datagram never made it to the server, or if the server's reply never made it back. If the client's request was something like "transfer a certain amount of money from account A to account B" (instead of our simple echo server), it would make a big difference as to whether the request was lost or the reply was lost. Elementary UDP Sockets
Srinu Bevara Page 7
connect Function with UDP an asynchronous error is not returned on a UDP socket unless the socket has been connected. Indeed, we are able to call connect for a UDP socket. But this does not result in anything like a TCP connection: There is no three-way handshake. Instead, the kernel just checks for any immediate errors (e.g., an obviously unreachable destination), records the IP address and port number of the peer (from the socket address structure passed to connect), and returns immediately to the calling process. Overloading the connect function with this capability for UDP sockets is confusing. If theconventionthat sockname is the local protocol address and peername is the foreign protocol address is used, then a better name would have been setpeername. Similarly, a better name for the bind function would be setsockname. With this capability, we must now distinguish between An unconnected UDP socket, the default when we create a UDP socket A connected UDP socket, the result of calling connect on a UDP socket With a connected UDP socket, three things change, compared to the default unconnected UDP socket: 1. We can no longer specify the destination IP address and port for an output operation. That is, we do not use sendto, but write or send instead. Anything written to a connected UDP socket is automatically sent to the protocol address (e.g., IP address and port) specified by connect. 2. We do not need to use recvfrom to learn the sender of a datagram, but read, recv, or recvmsg instead. The only datagrams returned by the kernel for an input operation on a connected UDP socket are those arriving from the protocol address specified in connect. Datagrams destined to the connected UDP socket's local protocol address (e.g., IP address and port) but arriving from a protocol address other than the one to which the socket was connected are not passed to the connected socket. This limits a connected UDP socket to exchanging datagrams with one and only one peer. 3. Asynchronous errors are returned to the process for connected UDP sockets. The corollary, as we previously described, is that unconnected UDP sockets do not receive asynchronous errors. Elementary UDP Sockets
Srinu Bevara Page 8
Lack of Flow Control with UDP We observe two cases: CASE 1: SLOW CLIENT FAST SERVER CASE 2: FAST CLIENT SLOW SERVER WE KNOW THE STATEMENT AT ANY MOMENT OF TIME, SENDER WILL NOT OVERFLOW THE RECEIVER BUFFER FROM TCP CONCEPT. Based on this statement, we explain the concept like this: W.r.to Client: SLOW-BIT RATE IS LESS FAST-BIT RATE IS MORE W.r.to Server: SLOW-RECEIVER BUFFER (WINDOW) SIZE IS LESS FAST- RECEIVER BUFFER (WINDOW) SIZE IS MORE In CASE 2, the Datagrams are lost to the maximum extent. This is the normal situation that is present in UDP Communication. In CASE 1, the Datagrams are maintained and delivered to the receiver (as there will be flow control). Consider the following example for CASE 2: The client sent 2,000 datagrams, but the server application received only 30 of these, for a 98% loss rate. is no indication whatsoever to the server application or to the client application that these datagrams were As we have said, UDP has no flow control and it is unreliable. It is trivial, as we have shown, for a UDP sender overrun the receiver. If we look at the netstat output, the total number of datagrams received by the server host (not the server application) is 2,000 (73,208 - 71,208). The counter "dropped due to full socket buffers" indicates how many Elementary UDP Sockets
Srinu Bevara Page 9
datagrams were received by UDP but were discarded because the receiving socket's receive queue was full 775 of TCPv2). This value is 1,970 (3,491 - 1,971), which when added to the counter output by the application. The following Output specifies this:
THE FIRST SET OF LINES IS WHEN THE DATAGRAMS ARE NOT YET OBTAINED AT THE CLIENT SIDE (BEFORE THIS COMMUNICATION). THE SECOND SET OF LINES IS WHEN DATAGRAMS ARE COMMUNICATED IN THIS (CURRENT) COMMUNICATION. This specifies clearly that there is lack of flow control with the UDP Service. Determining Outgoing Interface with UDP A connected UDP socket can also be used to determine the outgoing interface that will be used to a particular destination. This is because of a side effect of the connect function when applied to a UDP socket: The kernel chooses the local IP address (assuming the process has not already called bind to explicitly assign this). This local IP address is chosen by searching the routing table for the destination IP address, and then using the primary IP address for the resulting interface.
In the above figure, UDP Client connects with the UDP Server using bind(). But, in order for the datagrams to move from UDP Client to UDP Server, they should move through intermediate routers. So, PEER System now becomes R1 but not UDP Server. This is because we are using connect() within the UDP communication.