Getting Started with TCP client/server programming

Source: Internet
Author: User
Tags terminates htons

Recently in the study of UNP, hereby recorded.

1. TCP Callback Server program

#include"Unp.h"voidStr_echo (intsockfd)    {ssize_t n; CharBuf[maxline];again: while((n = Read (SOCKFD, buf, MAXLINE)) >0) writen (SOCKFD, buf, N); if(N <0&& errno = =eintr)Gotoagain; Else if(N <0) Err_sys ("Str_echo:read Error");}intMainintargcChar**argv) {    intLISTENFD, CONNFD;    pid_t Childpid;    Socklen_t Clilen; structsockaddr_in cliaddr, servaddr; LISTENFD= Socket (Af_inet, Sock_stream,0); Bzero (&AMP;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);  for (;;) {Clilen=sizeof(CLIADDR); CONNFD= Accept (LISTENFD, (SA *) &cliaddr, &Clilen); if((Childpid = Fork ()) = =0) {Close (LISTENFD);            Str_echo (CONNFD); Exit (0);    } Close (CONNFD); }}        

2. TCP Callback client program

#include"Unp.h"voidSTR_CLI (FILE *FP,intsockfd) {    CharSendline[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); }}intMainintargcChar**argv) {    intSOCKFD; structsockaddr_in servaddr; if(ARGC! =2) Err_quit ("usage:cli <ipaddress>"); SOCKFD= Socket (Af_inet, Sock_stream,0); Bzero (&AMP;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); Exit (0);}

At this point, a simple client/server program is written. Running the server program and client program, the back-firing function is normal.

However, the program still has problems at this point.

The first is the server program.

When the server child process terminates, a SIGCHLD signal is sent to the parent process, but we do not capture the signal in the code, and the default behavior of the signal is ignored. In this way, the child process eventually enters a zombie state.

Even if we write the SIGCHLD signal processing function, the server program still has a problem.

Because when the SIGCHLD signal is submitted to the parent process, the parent process is blocking the slow system call to accept. The kernel then causes the accept to return a EINTR error. The parent process does not handle the error and terminates. (Some systems automatically restart interrupted system calls)

Therefore, we must be prepared to return EINTR for slow system calls.

3. Fixed server program

#include"Unp.h"voidStr_echo (intsockfd)    {ssize_t n; CharBuf[maxline];again: while((n = Read (SOCKFD, buf, MAXLINE)) >0) writen (SOCKFD, buf, N); if(N <0&& errno = =eintr)Gotoagain; Else if(N <0) Err_sys ("Str_echo:read Error");}voidSIG_CHLD (intSigno)    {pid_t pid; intStat;  while(PID = Waitpid (-1, &stat, Wnohang)) >0) printf ("Child %d terminated\n", PID); return;}intMainintargcChar**argv) {    intLISTENFD, CONNFD;    pid_t Childpid;    Socklen_t Clilen; structsockaddr_in cliaddr, servaddr; LISTENFD= Socket (Af_inet, Sock_stream,0); Bzero (&AMP;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);    Signal (SIGCHLD, SIG_CHLD); /*must call Waitpid*/     for (;;) {Clilen=sizeof(CLIADDR); if(CONNFD = Accept (LISTENFD, (SA *) &cliaddr, &clilen)) <0)        {            if(errno =eintr)Continue;/* back to For*/            ElseErr_sys ("Accept Error"); }            if((Childpid = Fork ()) = =0) {Close (LISTENFD);            Str_echo (CONNFD); Exit (0);    } Close (CONNFD); }}        

The server program is correct, but the client program has some problems.

Consider a scenario in which a child process is killed with the kill command when the client establishes a TCP connection with the server and successfully performs a back-firing operation. The termination of the child process causes a fin to be sent to the client, but the client TCP receives the fin only to indicate that the server process has closed the server side of the connection and no longer sends any data to it. The receipt of fin did not inform the client that the TCP server process had been terminated. We need to modify the code (using the Select or poll function) so that when the termination of the server process occurs, the client can detect it.

It is also worth mentioning that in this case, the customer is actually dealing with two descriptors--sockets and user input. Instead of blocking the input of a particular source in either source, it should block the input of either of these sources.

The following code can fix the problem above.

voidSTR_CLI (FILE *FP,intsockfd) {    intMaxfdp1, stdineof;    Fd_set RSet; CharBuf[maxline]; intN; Stdineof=0; Fd_zero (&RSet);  for (;;) {        if(stdineof = =0) Fd_set (Fileno (FP),&RSet); Fd_set (SOCKFD,&RSet); MAXFDP1= Max (Fileno (FP), SOCKFD) +1; Select (MAXFDP1,&rset, NULL, NULL, NULL); if(Fd_isset (SOCKFD, &rset))/*socket is readable*/        {            if((n = Read (SOCKFD, buf, MAXLINE)) = =0)            {                if(stdineof = =1)                    return; ElseErr_quit ("Str_cli:server terminated prematurely");        } Write (Fileno (stdout), buf, N); }                if(Fd_isset (Fileno (FP), &rset))/*input is readable*/        {            if((n = Read (Fileno (FP), buf, MAXLINE)) = =0) {stdineof=1;                Shutdown (SOCKFD, SHUT_WR); FD_CLR (Fileno (FP),&RSet); Continue;        } Write (SOCKFD, buf, N); }     }}

Getting Started with TCP client/server programming

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.