TCP Client-Server Example
TCP Client-Server Example
TCP Client-Server Example
2
TCP Echo Server and Client
3
TCP Echo Server: main function
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
for ( ; ; ) {
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
5
TCP Echo Server: str_echo function
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 */
if (argc != 2)
err_quit("usage: tcpcli <IPaddress>");
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);
void
str_cli(FILE *fp, int sockfd)
{
char sendline[MAXLINE], recvline[MAXLINE];
Fputs(recvline, stdout);
}
}
8
Normal Startup and Termination
watching the sequences in client-server and TCP internals
Startup: socket, bind, listen, accept, connect, str_cli, fgets, accept, fork, str_echo
Termination: fgets, str_cli, exit, readline, str_echo, exit
11
signal Function That Enables System Call Restart
#include "unp.h" lib/signal.c
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_INTERRUPT
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
} else {
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; /* SVR4, 44BSD */
#endif
}
if (sigaction(signo, &act, &oact) < 0)
return(SIG_ERR);
return(oact.sa_handler); } 12
signal Function That Enables System Call Restart (cont.)
tcpcliserv/sigchldwait.c
#include "unp.h"
void
sig_chld(int signo)
{
pid_t pid;
int stat;
pid = wait(&stat);
printf("child %d terminated\n", pid);
return;
}
15
wait and waitpid Functions
cleaning up zombies
#include <sys/wait.h>
pid_t wait (int *statloc);
pid_t waitpid (pid_t pid, int *statloc, int options);
returns: process ID if OK, o, or -1 on error
Because signals are not queued, the signal handler is executed once
(if client and server run on the same host), twice or more (depending on
the timing of FINs arriving at the server host).
16
Client Terminates All Five Connections
catching all SIGCHLD signals in server parent
SIGCHLD
SIGCHLD
SIGCHLD
SIGCHLD
SIGCHLD
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
tcpcliserv/sigchldwaitpid.c
#include "unp.h"
void
sig_chld(int signo)
{
pid_t pid;
int stat;
20
Connection Abort Before accept Returns
implementation dependent !
client server
socket socket, bind, listen
connect (blocks) SYN LISTEN (passive open)
SYN,ack SYN_RCVD
connect returns
ack
RST ESTABLISHED
Problem:
The client should be aware of server process crash when FIN is received.
Solution:
Use select or poll to block on either socket or stdio.
22
SIGPIPE Signal
when 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 shell’s return value of last command.)
Solution:
Catch the SIGPIPE signal for further processing. The write operation
returns EPIPE.
23
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
socket 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
24
Summary of TCP Example
25
Data Format
string or binary between client and server
• In server process, add two numbers from client:
– In str_echo: sscanf converts string to long integer,
snprintf converts long back to string
• Pass binary structure between client and server
– does not work when the client and server are run on
hosts with different byte orders or sizes of long integer
• Different implementaions store binary, C datatype,
structure differently.
• Suggestions:
– pass in string only
– explicitly define the format of datatypes (e.g. RPC’s
XDR -- external data representation) 26