ch5-tcp client server example

Upload: sandeep-khandekar

Post on 04-Jun-2018

243 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/13/2019 Ch5-TCP Client Server Example

    1/47

    Chapter 5

    TCP Client/ServerExample

  • 8/13/2019 Ch5-TCP Client Server Example

    2/47

    TCP Client-Server Example TCP echo server: main and str_echo

    TCP echo client: main and str_cli

    Normal startup and termination

    POSIX signal handling

    Handling SIGCHILD, interrupted system calls,

    and preventing zombies Connection abort before accept returns

    Crash of server process

  • 8/13/2019 Ch5-TCP Client Server Example

    3/47

    SIGPIPE signal

    Crash, reboot, shutdown of server host

    Summary of TCP example

    Data format: passing string or binary

  • 8/13/2019 Ch5-TCP Client Server Example

    4/47

    TCP Echo Server and Client

    To expand this example to other applications,just change what the server does with the client input.

    Many boundary conditions to handle: signal, interruptedsystem call, server crash, etc. The first version does nothandle them.

  • 8/13/2019 Ch5-TCP Client Server Example

    5/47

    TCP Echo Server main() Algorithm A typical fork()-based concurrent server

    Algorithm outline : Create socket

    Bind it to a designated port (supposedly to be a well-knownport)

    Allow incoming traffic for any local network interface (wildcardaddress: INADDR_ANY)

    Convert it to a listening socket Set up a listening queue

    Loop around forever : Block in call to accept(), wait for a client to connect

    Spawn a child to handle each client upon successful connection Close listening socket

    Execute str_echo()

    Close connected socket for child. parent no wait 5

  • 8/13/2019 Ch5-TCP Client Server Example

    6/47

    TCP Echo Server: main

    function#include "unp.h"intmain(int argc, char **argv)

    { int listenfd, connfd;pid_t childpid;socklen_t clilen;struct sockaddr_in cliaddr, servaddr;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);Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

    tcpcliserv/tcpserv01.c

    9877

  • 8/13/2019 Ch5-TCP Client Server Example

    7/47

    Listen(listenfd, LISTENQ);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*/}

    }

  • 8/13/2019 Ch5-TCP Client Server Example

    8/47

    str_echo() Algorithm It provides very simple service for each client

    It reads data from a client and echoes it back to theclient

    Algorithm outline :

    Read a buffer from the connected socket If n (number of characters read) > 0,

    Echo back to the client (writen(): p. 89), read again

    Else if n < 0 & EINTR (got interrupt), read again Else just n < 0 (error occurred), display error message (and

    terminate child process in err_sys())

    Else if n = 0 (receipt of FIN from client, the normal scenario),return

    8

  • 8/13/2019 Ch5-TCP Client Server Example

    9/47

    TCP Echo Server: str_echo

    function#include "unp.h"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);}

    }

    lib/str_echo.c

  • 8/13/2019 Ch5-TCP Client Server Example

    10/47

    TCP Echo Client main() Algorithm Algorithm outline :

    Check number of commandline arguments It must be 2 (program name and server address)

    Quit if not 2 (call to sys_quit())

    Open socket

    Fill in internet socket address structure

    Connect to server

    Call str_cli() to handle the rest of the client processing

    Exit when no more user input

    Note: All errors end up in termination of theclient in this function. Real applications may needto recover differently 10

  • 8/13/2019 Ch5-TCP Client Server Example

    11/47

    TCP Echo Client: main

    function#include "unp.h"int main(int argc, char **argv){

    int sockfd;

    struct sockaddr_in servaddr;if (argc != 2)

    err_quit("usage: tcpcli ");sockfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));str_cli(stdin, sockfd); /* do it all */exit(0);

    }

    tcpcliserv/tcpcli01.c

  • 8/13/2019 Ch5-TCP Client Server Example

    12/47

    TCP Echo Client: str_cli

    function#include "unp.h"voidstr_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);}

    }

    lib/str_cli.c

  • 8/13/2019 Ch5-TCP Client Server Example

    13/47

    Normal Startup (1/2) To watch the sequence of client/server

    To start the server in background :linux% tcpserv01 &

    [1] 17870

    To check the status of all sockets on a system (-a)

    before the client starts :linux% netstat a

    Active Internet connections (servers and established)Proto Recv-Q Send-Q Local Address Foreign Address State

    tcp 0 0 *:9877 *:* LISTEN

    Note : The output above shows only partial results, and the outputformat may be different from system to system

    13

  • 8/13/2019 Ch5-TCP Client Server Example

    14/47

    Normal Startup (2/2) To start the client on the same machine (using the

    loopback address) :linux% tcpcli01 127.0.0.1

    Then, check the status of all sockets again :linux% netstat a

    Active Internet connections (servers and established)

    Proto Recv-Q Send-Q Local Address Foreign Address State

    tcp 0 0 localhost:9877 localhost:42758 ESTABLISHED

    tcp 0 0 localhost:42758 localhost:9877 ESTABLISHED

    tcp 0 0 *:9877 *:* LISTEN

    Note : The first tcp connection is for the server child, and thesecond is for the client, and the third is the server parent

    14

  • 8/13/2019 Ch5-TCP Client Server Example

    15/47

  • 8/13/2019 Ch5-TCP Client Server Example

    16/47

    Normal Termination (2/2)

    server TCPFINserver childreadlinereadline0

    server childstr_echomain Server childexitserver TCP(server childclient)

    Server childzombie

  • 8/13/2019 Ch5-TCP Client Server Example

    17/47

    Zombie Process

    ()

  • 8/13/2019 Ch5-TCP Client Server Example

    18/47

    Cleaning Up Zombie Processes

    Child processzombie

    Zombiechildparentkernel

    Parentzombie

    kernelsignal(SIGCHLD)

  • 8/13/2019 Ch5-TCP Client Server Example

    19/47

    POSIX Signal Handling

    Signal (software interrupt): sent by oneprocess to another process (or to itself) or bythe kernel to a process

    SIGCHLD: by the kernel to the parent whena child process is terminated

    Disposition of a signal:

    catch the signal by a specified signal handler SIG_IGN: ignore it

    SIG_DFL: default: terminate or ignore

  • 8/13/2019 Ch5-TCP Client Server Example

    20/47

    signal Function That EnablesSystem Call Restart#include "unp.h"Sigfunc *signal(int signo, Sigfunc *func){

    struct sigaction act, oact;act.sa_handler = func;

    sigemptyset(&act.sa_mask);act.sa_flags = 0;if (signo == SIGALRM) {

    #ifdef SA_INTERRUPTact.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */

    #endif} else {

    #ifdef SA_RESTARTact.sa_flags |= SA_RESTART; /* SVR4, 44BSD */

    #endif}if (sigaction(signo, &act, &oact) < 0)return(SIG_ERR);

    return(oact.sa_handler);}

    singalsystem callrestart

    Posixsignal dispositionsigactionsignalsigaction

    lib/signal.c

  • 8/13/2019 Ch5-TCP Client Server Example

    21/47

  • 8/13/2019 Ch5-TCP Client Server Example

    22/47

    Handling Zombies

    Whenever we fork children, we must waitfor them to prevent them from becoming

    Zombies

    To do this, we establish a signal handler to

    cache SIGCHLD

    and within the handler we call wait.

  • 8/13/2019 Ch5-TCP Client Server Example

    23/47

    Signal Handler for SIGCHLD

    #include "unp.h"voidsig_chld(int signo){

    pid_t pid;int stat;pid = wait(&stat);

    printf("child %d terminated\n", pid);return;}

    tcpcliserv/sigchldwait.c

    child

    process id

    waitchildzombie

  • 8/13/2019 Ch5-TCP Client Server Example

    24/47

    Interrupted System Calls

    kernelSIGCHLD signalparentparentblockacceptsystem callsystem callinterrupthandler

    signal handler returninterruptedsystem callrestartsystem call(EINTR) signalrestart system call

    EINTRAccept(abort)

  • 8/13/2019 Ch5-TCP Client Server Example

    25/47

    Handling Interrupted SystemCalls

    Definition: Slow system call system call that canblock forever

    Some kernels automatically restart some interrupted

    system calls, while some dont We must prepare for slow system calls to return EINTR

    for ( ; ; ){clilen = sizeof (cliaddr);

    if ( (connfd = accept (listenfd, (SA) &cliaddr, &clilen)) < 0) {if (errno == EINTR) continue; /* back to for ( ) */else err_sys (accept error);

    }restart acceptsystem call

  • 8/13/2019 Ch5-TCP Client Server Example

    26/47

  • 8/13/2019 Ch5-TCP Client Server Example

    27/47

    Client terminates all fiveconnections

    catching all SIGCHLD signals in server parent

  • 8/13/2019 Ch5-TCP Client Server Example

    28/47

    SIGCHLD HandlerUsingWaitpid

    #include "unp.h"voidsig_chld(int signo){

    pid_t pid;int stat;

    while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)printf("child %d terminated\n", pid);return;

    }

    #include pid_t waitpid (pid_t pid, int *statloc, int options);

    returns: process ID if OK, o, or -1 on error

    Wait for the first terminated child

    Not block if there areno terminated children

  • 8/13/2019 Ch5-TCP Client Server Example

    29/47

    Final (correct) Version of TCPEcho Serverhandling SIGCHLD, EINTR from accept, zombies

    #include "unp.h"intmain(int argc, char **argv)

    {int listenfd, connfd;pid_t childpid;socklen_ t clilen;struct sockaddr_in cliaddr, servaddr;void sig_chld(int);

    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);Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

    Listen(listenfd, LISTENQ);

    tcpcliserv/tcpserv04.c

  • 8/13/2019 Ch5-TCP Client Server Example

    30/47

  • 8/13/2019 Ch5-TCP Client Server Example

    31/47

    Connection Abort Beforeaccept Returnsimplementation dependent !

    In BSD, kernel handles this. accept does not return.In SVR4, accept is returned with EPROTO.

    In POSIX.1g, accept is returned with ECONNABORTEDThe server can ignore the error and just call accept again

  • 8/13/2019 Ch5-TCP Client Server Example

    32/47

    Crashing of Server ChildProcess

    Procedure:1. Kill the child. 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. User inputs. 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.

    The client is blocked on the call to fgets when FIN isreceived.(it should block on input from either source)Solution:Use select or poll to block on either socket or stdio

    Clientinput

  • 8/13/2019 Ch5-TCP Client Server Example

    33/47

    SIGPIPE Signalwhen writing to a socket that has received an RST

    Procedure:1. The client writes to a crashed server process. An RST is received

    at the client TCP and readline returns 0 (EOF).2. If the client ignores the error returned from readline and write more,

    SIGPIPE is sent to the client process.3. If SIGPIPE is not caught, the client terminates with no output

    Problem:

    Nothing is output even by the shell to indicate what has happened.(Have to use echo $?to examine the shells return value of last command.)

    Solution:1. Setting the signal disposition to SIG_IGN2. Catch the SIGPIPE signal for further processing. (handle EPIPE error

    returned from write).

  • 8/13/2019 Ch5-TCP Client Server Example

    34/47

  • 8/13/2019 Ch5-TCP Client Server Example

    35/47

  • 8/13/2019 Ch5-TCP Client Server Example

    36/47

    Crash of Server Host

    Scenario 1. client and server run on different hosts 2. make a connection between client and server 3. client types something to transmit data to the server 4. disconnect the server host from the network (destination

    unreachable) 5. client types something again.

    client TCP continuously retx data and timeout around 9 min The client process will then return with the error ETIMEDOUT. If some intermediate router determined that the server host was down

    and responded with an ICMPdestination unreachable

    message, theerror returned will then be either EHOSTUNREACH or ENETUNREACH

    To quickly detect: timeout on readline, SO_KEEPALIVE socketoption, heartbeat functions

  • 8/13/2019 Ch5-TCP Client Server Example

    37/47

    Reboot of Server Host

    The client does not see the server hostshut down

    Client sends data to server after theserver reboots

    server TCP responds to client data with

    an RST because it loses all connectioninformation

    readline returns ECONNRESET

  • 8/13/2019 Ch5-TCP Client Server Example

    38/47

    Shutdown of Server Host (byOperator)

    init process sends SIGTERM to allprocesses

    We can catch this signal and close all opendescriptors by ourselves

    init waits 5-20 sec and sends SIGKILL

    to all processes all open descriptors are closed by kernel

  • 8/13/2019 Ch5-TCP Client Server Example

    39/47

    Summary of TCP Example

    From clients perspective:

    socket and connect specifies servers port and

    IP client port and IP chosen by TCP and IP

    respectively

    From servers perspective:

    socket and bind specifies servers local port andIP

    listen and accept return clients port and IP

  • 8/13/2019 Ch5-TCP Client Server Example

    40/47

    TCP Client/Server Clients Perspective

    40

  • 8/13/2019 Ch5-TCP Client Server Example

    41/47

    TCP Client/Server Clients Perspective

    41

  • 8/13/2019 Ch5-TCP Client Server Example

    42/47

    Data Format: Text Strings

    server process gets two numbers (in aline of text) from client and returns

    their sum In str_echo: sscanf converts string to

    long integer, snprintf converts long

    back to string

  • 8/13/2019 Ch5-TCP Client Server Example

    43/47

    str_echo() Adding 2 Numbers

    tcpcliserv/str_echo08.c

    43

  • 8/13/2019 Ch5-TCP Client Server Example

    44/47

    Data Format: Binary Structure

    Passing binary structure between client andserver does not work when the client and server are run on hosts with

    different byte orders or sizes of long integer

    Since different implementations can store thesame C datatype differently.

    Suggestions: pass in string only explicitly define the format of data types (e.g.

    RPCs XDR -- external data representation)

  • 8/13/2019 Ch5-TCP Client Server Example

    45/47

    str_cli() Sending 2 Binary Ints

    tcpcliserv/str_cli09.c

    45

  • 8/13/2019 Ch5-TCP Client Server Example

    46/47

    str_echo() Adding 2 Binary Ints

    tcpcliserv/str_echo09.c

    46

  • 8/13/2019 Ch5-TCP Client Server Example

    47/47

    Beware of Different Byte Orders

    Due to the big-endian and little-endian implementations,sending binary numbers between different machinearchitectures may end up with different results

    An example of two big-endian SPARC machines : solaris% tcpcli09 12.106.32.254

    11 12 # user input in bold

    33 # result back from server

    -11 -14

    -55

    An example of big-endian SPARC and little-endian Intel machines : linus% tcpcli09 206.168.112.96

    1 2 # user input in bold

    3 # It seems to work

    -22 -77

    -16777314 # oops! It does not work!