20.4 Request-Reply Protocols

Team-FLY

In the simple-request protocol, the client cannot distinguish the scenario of Figure 20.3 from those of Figure 20.4 and Exercise 20.7 because it does not receive an acknowledgment of its request or any results produced by the request. A request-reply protocol handles this problem by requiring that the server respond to the client. Figure 20.5 shows a sequence of steps, using UICI UDP, to implement a simplified request-reply protocol. If no errors occur, the server's reply message notifies the client that the transmission was successful. The server reply message can contain actual results or just a flag reporting the status of the request.

Figure 20.5. Sequence of steps in an error-free request-reply protocol.

graphics/20fig05.gif

Program 20.3 shows the server-side implementation of the request-reply protocol of Figure 20.5. The server receives a request and uses u_gethostinfo to extract the identity of the client. After printing the client's name and request to STDOUT_FILENO , the server uses u_sendto with the u_buf_t structure ( senderinfo ) returned from u_recvfrom to respond to that client. The UICI UDP u_sendto function uses the u_buf_t structure as the destination address to ensure that the reply is directed to the correct client. The server shown here replies with a copy of the request it received.

Exercise 20.8

An important consideration in writing a server is to decide which conditions should cause the server to exit, which conditions should be ignored, which conditions should be logged and which conditions should trigger a recovery procedure. The server of Program 20.3 never exits on its own once its port is bound to the socket. You can terminate the server by sending it a signal. Under what conditions would it be reasonable for a server such as an ftp server to exit?

Answer:

You could argue that an ftp server should never exit because it should be running at all times. Certainly, an error caused by a client should not terminate the server. Even if system resources are not available to handle a connection, the problem might be temporary and the server would continue to work after the problem is resolved. Errors should be logged so the administrator has a record of any problems.

Program 20.3 server_udp_request_reply.c

A server program that implements a request-reply protocol .

 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "restart.h" #include "uiciudp.h" #define BUFSIZE 1024 int main(int argc, char *argv[]) {    char buf[BUFSIZE];    ssize_t bytesread;    char hostinfo[BUFSIZE];    u_port_t port;    int requestfd;    u_buf_t senderinfo;    if (argc != 2) {       fprintf(stderr, "Usage: %s port\n", argv[0]);       return 1;    }    port = (u_port_t) atoi(argv[1]);         /* create UDP endpoint for port */    if ((requestfd = u_openudp(port)) == -1) {       perror("Failed to create UDP endpoint");       return 1;    }    for ( ; ; ) {                /* process client requests and send replies */       bytesread = u_recvfrom(requestfd, buf, BUFSIZE, &senderinfo);       if (bytesread == -1) {          perror("Failed to receive client request");          continue;       }       u_gethostinfo(&senderinfo, hostinfo, BUFSIZE);       if ((r_write(STDOUT_FILENO, hostinfo, strlen(hostinfo)) == -1)            (r_write(STDOUT_FILENO, buf, bytesread) == -1)) {          perror("Failed to echo client request to standard output");       }       if (u_sendto(requestfd, buf, bytesread, &senderinfo) == -1) {          perror("Failed to send the reply to the client");       }    } } 

Program 20.4 shows a client that uses the request-reply protocol of Figure 20.5. The request is just a string containing the process ID of the requesting process. The protocol is implemented in the request_reply function shown in Program 20.5. The client sends the initial request and then waits for the reply. Since anyone can send a message to an open port, the client checks the host/port information against the sender information supplied in senderinfo to make sure that it received the reply from the same host that it sent to.

Program 20.4 client_udp_request_reply.c

A client program that sends a request containing its process ID and reads the reply .

 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "restart.h" #include "uiciudp.h" #define BUFSIZE 1024 int request_reply(int requestfd, void* request, int reqlen,                   char* server, int serverport, void *reply, int replen); int main(int argc, char *argv[]) {    ssize_t bytesread, byteswritten;    char reply[BUFSIZE];    char request[BUFSIZE];    int requestfd;    u_port_t serverport;    if (argc != 3) {       fprintf(stderr, "Usage: %s servername serverport\n", argv[0]);       return 1;    }    serverport = (u_port_t) atoi(argv[2]);    if ((requestfd = u_openudp(0)) == -1) {     /* create unbound UDP endpoint */       perror("Failed to create UDP endpoint");       return 1;    }    sprintf(request, "[%ld]\n", (long)getpid());           /* create a request */                               /* use request-reply protocol to send a message */    bytesread = request_reply(requestfd,  request, strlen(request)+1,                          argv[1], serverport, reply, BUFSIZE);    if (bytesread == -1)       perror("Failed to do request_reply");    else {       byteswritten = r_write(STDOUT_FILENO, reply, bytesread);       if (byteswritten == -1)          perror("Failed to echo server reply");    }    if ((r_close(requestfd) == -1)  (bytesread  == -1)  (byteswritten == -1))       return 1;    return 0; } 
Exercise 20.9

What happens when the scenario of Figure 20.4 occurs for the request-reply protocol of Figure 20.5?

Answer:

The client hangs indefinitely on the blocking u_recvfrom call.

Program 20.5 request_reply.c

Request-reply implementation A ”assumes error-free delivery .

 #include <sys/types.h> #include "uiciudp.h" int request_reply(int requestfd, void* request, int reqlen,                   char* server, int serverport, void *reply, int replen) {    ssize_t nbytes;    u_buf_t senderinfo;                                                          /* send the request */    nbytes = u_sendtohost(requestfd, request, reqlen, server, serverport);    if (nbytes == -1)       return (int)nbytes;                         /* wait for a response, restart if from wrong server */    while ((nbytes = u_recvfrom(requestfd, reply, replen, &senderinfo)) >= 0 )       if (u_comparehost(&senderinfo, server, serverport))    /* sender match */          break;    return (int)nbytes; } 
Exercise 20.10

Compile Programs 20.3 and 20.4. Start the server on one machine (say, yourhost ) with the following command.

 server_udp_request_reply 20001 

Run clients on different hosts by executing the following on several machines.

 client_udp_request_reply yourhost 20001 

Put timing statements in Program 20.4 to measure how long it takes for the client to send a request and receive a response. (See Example 9.8.) Run the client program several times. Do any of the instances hang? Under what circumstances would you expect the client to hang?

Answer:

The client blocks indefinitely on u_recvfrom if it does not receive the reply from the server. Modern networks have become so reliable that if the client and server are running on the same local area network (LAN), it is unlikely that either the request or the reply messages will be lost because of errors along particular wires. In high-congestion situations, packets may be dropped at LAN switches. If many clients are making simultaneous requests, the network subsystem of the server host might discard some packets because the communication endpoint's buffers are full. Messages from clients and servers on different LANs generally follow paths consisting of many links connected by routers. Congested routers drop messages that they can't handle, increasing the likelihood that a message is not delivered.

Exercise 20.11

Figure 20.6 illustrates the timing for the request-reply protocol when there are no errors. When errors are possible, the nine events listed in the following table can occur in various orders.

event

description

A

client sends request message

B

server receives request message

C

server processes request

D

server sends reply message

E

client receives reply message

F

request message is lost

G

reply message is lost

H

client crashes

I

server crashes

The event sequence ABCDE represents the scenario of Figure 20.6. For the five event sequences listed below, state whether each represents a physically realizable scenario. If the scenario is realizable, explain the outcome and draw a timing diagram similar to that shown in Figure 20.6. If the scenario is not realizable, explain why.

  1. ABCED

  2. ABCDG

  3. ABCI

  4. ABCGD

  5. ABCDIE

What other event sequences represent possible scenarios for request-reply?

Answer:

  1. ABCED is not realizable, since the client cannot receive a message before the server sends it. This assumes that no other process on the server host has guessed the ephemeral port number used by the client and sent a bogus reply. It also assumes that another host has not spoofed the IP address of the server. We do not consider these scenarios here.

  2. ABCDG is realizable and represents a situation in which the client does not receive a response even though the server has processed the request.

  3. ABCI is realizable and represents a situation in which the server receives the request and processes it but crashes before it sends the response.

  4. ABCGD is not realizable, since a message cannot be lost before it is sent.

  5. ABCDIE is possible. If the server crashes after it sends the reply, the reply can still be received.

Many other event sequences represent realizable scenarios.

Figure 20.6. Timing diagram of the request-reply protocol.

graphics/20fig06.gif

Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net