Vous êtes sur la page 1sur 36

TCP Client-Server Example

III-Unit

Contents
Introduction TCP Echo Server TCP Echo Client Normal Startup and Termination Posix Signal Handling Handling SIGCHLD Signals Data Format and so on...

5.1 Introductioon
stdin stdout
fgets writen readline readline writen

fputs

TCP client

TCP server

1. The Client reads a line of text from its standard input and writes the line to the server. 2. The server reads the line from its network input and echoes the line back to the client. 3. The client reads the echoed line and prints it on its standard output.

5.2 TCP Echo Server


main function & str_echo function
for ( ; ; ) { clilen = sizeof(cliaddr); connfd = Accept(listenfd, (SA *) &cliaddr, &clilen); if ( (childpid = Fork()) == 0) {/* child process */ Close(listenfd);/* close listening socket */ str_echo(connfd);/* process the request */ exit(0); } Close(connfd); /* parent closes connected socket */ }

void str_echo(int sockfd) { ssize_t n;

char

line[MAXLINE];

for ( ; ; ) { if ( (n = Readline(sockfd, line, MAXLINE)) == 0) return; /* connection closed by other end */ Writen(sockfd, line, n); } }

5.4 TCP Echo Client


main function & str_cli function
Connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); str_cli(stdin, sockfd); /* do it all */ exit(0);

void str_cli(FILE *fp, int sockfd) { char sendline[MAXLINE], recvline[MAXLINE];

while (Fgets(sendline, MAXLINE, fp) != NULL) { Writen(sockfd, sendline, strlen(sendline)); if (Readline(sockfd, recvline, MAXLINE) == 0) err_quit("str_cli: server terminated prematurely");

Fputs(recvline, stdout);
} }

Normal Startup
How the client and server start, how they end What happens when something goes wrong
the client host crashes, the client process crashes, network connectivity is lost

Test method We first start the server in the background on the host linux
tcpserv & When the server starts, it calls socket, bind,listen and accept .

Before starting the client , we run the netstat program to verify the state of the servers listening sockets netstat a tcpcli 127.0.0.1 (local test) netstat a ps -l

Normal Termination
At this point, the connection is established and whatever we type to the client is echoed back. tcpcli 127.0.0.1
hello, world hello, world good bye good bye ^D We type Control-D,which terminates the client., if we immediately execute netstat, we have netstat -a | grep procID

Crashing of Server Process


Is the client aware of ?
Procedure: 1. Server TCP sends FIN to client TCP, which responds with an ACK. (TCP half-close) (The client process is blocked in fgets when client TCP receives FIN.) 2. SIGCHLD signal is sent to the server parent. 3. The client process calls writen to send data to server. 4. The server TCP responds with an RST. 5. The client process returns from readline, 0, when client TCP receives RST. 6. The client process terminates.

Problem: The client should be aware of server process crash when FIN is received.

Solution: Use select or poll to block on either socket o r stdio.

Crash, Reboot, Shutdown of Server Host Crash of server host:


client TCP continuously retx data and timeout around 9 min readline returns ETIMEDOUT or EHOSTUNREACH To quickly detect: timeout on readline, SO_KEEPALIVE so cket option, heartbeat functions

Reboot of server host:


After reboot, server TCP responds to client data with an RST readline returns ECONNRESET

Shutdown (by operator) of server host:


init process sends SIGTERM to all processes init waits 5-20 sec and sends SIGKILL to all processes

5.8 Posix Signal Handling


SIGALRM
place a timeout on an I/O operation

SA_RESTART
a system call interrupted by this signal will be automatically restarted by the kernel

5.8 Posix Signal Handling


Posix Signal Semantics
Once a signal handler is installed, it remains installed. While a signal handler is executing, the signal being delivered is blocked. If a signal is generated one or more times while it is blocked, it is normally delivered only one time after the signal is unblocked. That is, by default Unix signals are not queued. It is possible to selectively block and unblock a set of signals using the sigprocmask function.

Handling SIGCHLD Signals


Zombie State
maintain information about the child for the parent to fetch at some later time
the process ID of the child, its termination status, the resource of the child(CPU time, memory) the parent process ID of all the zombie children: 1(init process)-inherit the children and clean them up <defunct>

Handling Zombies
space waste of the kernel, out of process wait for the children to prevent them from becoming zombies

Handling SIGCHLD Signals


We establish the signal handler by adding the function call
Signal (SIGCHLD, sig_chld);

in Figure 5.2, after the call to listen.


#include "unp.h" void sig_chld(int signo) { pid_t pid; int stat; pid = wait(&stat); printf("child %d terminated\n", pid); return; } Figure 5.7 Version of SIGCHLD signal handler that calls wait

Tcpserv02 & tcpcli01 127.0.0.1


hi, there hi, there ^D child 16942 terminated accept error: Interrupted system call // the parent is blocked in its call to accept when the SIGCHLD is delivered //sig_chld function executes, wait fetches the childPID and termination status, printf // kernel causes the accept to return an error of EINTER

5.9 Handling SIGCHLD Signals


Handling Interrupted System Calls
for ( ; ; ) { clilen = sizeof(cliaddr); if( (connfd=accept(listenfd,(SA *) &cliaddr,&clilen)) < 0) { if( errno == EINTER ) continue; else err_sys(accept error); }

5.10 wait and waitpid Functions


#include <sys/wait.h> pid_t wait(int *statloc); pid_t waitpid(pid_t pid, int *statloc, int option);

pit_t: the process ID of the terminated child statloc : the termination status of the child(an integer) is returned through the statloc pointer. pid : specify the process ID that we want to wait for. A value of -1 say to wait for the first of our children to terminate. option : specify additional option. The most common option is WNOHANG.

>tcpserv03 & >tcpcli03 206.62.226.35 hello hello ^D child 21288 terminated

21282 21284 21285 21286 21287

p1 S ./tcpserv03 p1 Z (tcpcli03) p1 Z (tcpcli03) p1 Z (tcpcli03) p1 Z (tcpcli03)

5.10 wait and waitpid Functions


Difference between wait and waitpid
the problem is that all five signals are generated before the signal handler is executed, and the signal handler is executed only one time because Unix signals are normally not queued.

waitpid
we must specify the WNOHANG option: this tells waitpid not to block if there exist running children that have not yet terminated.
void sig_chld(int signo) { pid_t pid; int stat; while((pid = waitpid(-1,&stat,WNOHANG)) > 0) printf("child %d terminated\n", pid); return; }

5.11 Connection Abort before accept Returns


The three-way handshake completes, the connection is established, and then the client TCP sends an RST(reset). On the server side the connection is queued by its TCP, waiting for the server process to call accept when the RST arrives. Some time later the server process calls accept.

Implementation BSD : kernel SVR4 : return an errno of EPROTO Posix.1g : return an errno of ECONNABORTED EPROTO : returned when some fatal protocol-related events occur on the streams subsystem. In the case of the ECONNABORTED error, the server can ignore the error and just call accept again.

5.12 Termination of Server Process


solaris % tcpcli01 206.62.226.35 hello hello another line str_cli: server terminated prematurely

Our client is not expecting to receive an end-offile at this point so it quits with the error message server terminated prematurely.

SIGPIPE Signal
What happens if the client the error return from readline and writes more data to the server ?
When a process writes to a socket that has received an RST, the SIGPIPE signal is sent to the process
Default action of SIGPIPE: terminate the process

>tcpcli11 206.62.226.34 hi there hi there bye

Nothing is echoed for bye data Reason: the default action of SIGPIPE is terminate the process.

What happens when the server host crashes, reboots, shutdowns

Vous aimerez peut-être aussi