Client-Server模式的TCP/IP網絡編程中,當客戶端與服務器端建立起TCP連接時,我們會
遇到連接中斷的情況,此時怎樣處理呢?
首先,我們應使兩端的通訊進程儘量"健壯"些,以避免一些干擾。爲此,我們可以調用S
ignal (SIGINT, SIG_IGN)、singnal (SIGHUP, SIG_IGN)、signal (SIGQUIT, SGI_IGN),
來屏蔽掉一些可以導致進程終止的信號。
其次,當一TCP連接中斷時,對基於該連接的socket的系統調用read的返回值爲0,由此,
我們可以設計服務器端的代碼如下:
# include
# include
# include
# include
# include
# include
struct msgdata {
long msgtype;
char msgdata [1024];
}
main (argc, argv)
int argc;
char **argv;
{
int forkid;
if (argc !=2
{
printf (:usages:%s localport/n", argv[0]);
exit(2);
}
signal (SIGINT, SIG_IGN)
signal (SIGHUP, SIG_IGN)
signal (SIGQUIT, SIG_IGN)
signal (SIGTERM, SIG_IGN)
for (;;) {
if((forkid=fork())==0) lmsgl(atoi (argv[1]);
else
{
wait (( int*)0); /* here this process is waiting for the creat
ed
sleep(5)
} /*process to be dead
}
}
lmsgl (localport)
int localport;
{
long forkid;
int namelen, newsock, sock, i, datalen;
int goback ();
struct msgdata td, rd;
struct sockaddr-in sin={AF_INET};
sin. sin-prort=localport;
datalen=sizeof (struct msgdata);
namelen=sizeof (sin);
if((sock=socket (AF-INET, DOCK-STREAM, IPPROTO-TCP))<=0)
{
perror ("socket");
exit (1);
}
if(bind (sock, &sin, sizeof (sin))<0)
{ perror ("bind");
exit(2);
}
if (getsockname (sock, &sin, &namelen)<0)
{
perror ("getsockname");
exit(2);
}
printf ("Server bound to port %u 0x%x/n", ntohs (sin, sin-port), sin.s
in-port);
if (listen (sock, 5)<0)
{ perror ("listen");
exit (4);
}
if ((newsock=accept (sock, &sin, &namelen))<0)
{ perror ("accept");
exit (5);
}
switch (forkid=fork()) {
case-1;
/*error number returned!
printf ("fork error/n:);
perror ("fork");
exit (5);
case
close (sock);
for (;;)
{
i=read (newsock, &rd, datalen);
if (i==0)
{
printf("/nthe connection is terminated!/n");
close (newsock);
exit (6);
}
/*Bere we kill the child process and
/*send SIGHLD to the parent process
do something we are interesting.....
}
default: /*the parent process
close (sock);
signal (SIGHLD, goback (newsock));
/*catching the SIGCHLD signal, jump to the beginning
for (;;)
//do something we are interesting.....
{
i=write (newsock, &td, datalen);
if (i=-1)
{
printf ("TCP/IP write error!/n");
perror ("write");
continue;
} /*end of switch
} /*end of lmsge
goback (newsock)
int newsock;
{
signal (SIGINT, SIG_IGN);
close (newsock);
printf ("Go Back to Beginning/n");
exit (7);
}
以上代碼中,一祖父進程調用fork ()創建一父進程,然後掛起父進程,等待客戶端的連
接請求,一旦TCP連接建立起來,父進程又創造一子進程;此時父進程負責向已建立連接的ne
wsock中寫入信息,子進程負責從newsock中讀取信息。當TCP連接中斷時,子進程的read返回
值爲0,那麼它便終止運行;同時向父進程發送SIGCHLD信號。在父進程中,我們設置signal
(SIGCHLD, goback),當捕捉到SIGCHLD信號時,提示中斷信息,然後終止進程。由於我們在祖
父進程中,用wait ( (int *) 0)來實現進程同步,這時祖父進程便被激活,它啓動另外一父
進程,等待客戶端的連接請求,當請求到來時,新的TCP連接便能建立起來。
另外,在某些情況下,我們可以把Client-Server模式做得對等起來,也就是說一端既可
以等待連接要求,也可以主動地請求連接。這樣當TCP連接中斷時,通信系統的兩端便能智能
地在server、Client之間隨機轉換,直到TCP連接建立,此時的通訊系統便很少需要人爲的幹
預,這樣的模式做起來需要些技巧,留作以後討論。