Zombie Process Processing
1) Avoid the zombie process by ignoring the SIGCHLD signal
Adding in server-side code
Signal (SIGCHLD, sig_ign);
2) solve the zombie process through the Wait/waitpid method
Signal (sigchld,onsignalcatch); void Onsignalcatch (int signalnumber) { wait (NULL);}
3) If multiple clients are closed at the same time, the problem description is shown in the following two images:
/** client-side implementation of the test Code **/int main () { int sockfd[50]; for (int i = 0; i < ++i) { if (sockfd[i] = socket (af_inet, sock_stream, 0)) = =-1) err_exit ("Socket ER Ror "); struct sockaddr_in serveraddr; serveraddr.sin_family = af_inet; Serveraddr.sin_port = htons (8001); SERVERADDR.SIN_ADDR.S_ADDR = inet_addr ("127.0.0.1"); if (Connect (sockfd[i), (const struct sockaddr *) &serveraddr, sizeof (serveraddr)) = =-1) err_exit ("Connect Error "); } Sleep (20);}
By pressing CTRL + C while the client is running, you can see that the number of zombie processes that are generated when the server side starts 50 sub-processes and all of the clients are disconnected together is amazing (and this proves that the SIGCHLD signal is unreliable)!
Workaround-Transform the server-side signal capture function as follows:
void Sighandler (int signo) {while (Waitpid ( -1, NULL, Wnohang) > 0) ;}
Waitpid return value Explanation:
On success, returns the process ID of the "the child" whose state has changed (return has ended running
PID of the child process); If Wnohang is specified and one or more child (ren) specified by PID exist,
but the yet changed state and then 0 are returned ( if there are still many sub-processes identified by the PID parameter , and
And there is no sign of ending, return 0). On error,-1 is returned.
Address Query API
#include <sys/socket.h>int getsockname (int sockfd, struct sockaddr *addr, socklen_t *addrlen);//get local addr struct int Getpeername (int sockfd, struct sockaddr *addr, socklen_t *addrlen);//Get the other addr structure int gethostname (char *name, size_t len); int sethostname (const char *name, size_t len), #include <netdb.h>extern int h_errno;struct hostent *gethostbyname ( const char *name); #include <sys/socket.h> /* for af_inet */struct hostent *gethostbyaddr (const void *ADDR, sock len_t len, int type), struct hostent *gethostent (void);
/** get the native IP list **/int gethostip (char *ip) { struct hostent *hp = gethostent (); if (HP = = NULL) return-1; strcpy (IP, inet_ntoa (* (struct in_addr*) hp->h_addr)); return 0;} int main () { char host[128] = {0}; if (gethostname (host) = =-1) err_exit ("GetHostName error"); cout << "Host-name:" << host << Endl; struct Hostent *hp = gethostbyname (host); if (HP = = NULL) err_exit ("gethostbyname error"); cout << "IP list:" << Endl; for (int i = 0; Hp->h_addr_list[i]! = NULL; ++i) { cout << ' \ t ' << inet_ntoa (* (struct IN_ADD r*) hp->h_addr_list[i]) << Endl; } Char ip[33] = {0}; Gethostip (IP); cout << "LOCAL-IP:" << IP << Endl;}
11 States of the TCP protocol
1. (both client and server are in this machine: Both sides (child process of server, with client) Link has been established (established), waiting for communication)
2. One end of the first close will enter the TIME_WAIT state; One end of the passive shutdown can enter the Close_wait state (the server side is first closed)
3.time_wait time is 2MSL (twice times the maximum lifetime of the message)
Reason: (ACK y+1) if the sending failure can be re-sent, so if the server side does not set the address reuse, the server in a short period of time will not be restarted;
The server side is in closed state, not equal to the client is also in the closed state.
(, client first close, client appears time_wait state)
The 1th state of the 4.TCP/IP protocol: There are only 10 states on the graph and a CLOSING state
Causes of closing status:
The server side shuts down simultaneously with the client side (while calling Close, at which point both ends send fin packets to the peer), the closing state is generated, and both sides enter the TIME_WAIT state (for example).
Sigpipe Signal
It is permissible to write to a socket that has received fin, and to receive fin just means that the other party no longer sends the data, but after receiving the RST segment, if you continue to write, the call to write will produce a sigpipe signal, which we usually ignore for processing this signal.
Signal (sigpipe, sig_ign);
/** test: Send each message in the client sends two times when the server side shuts down, the server sends a FIN section to the client, and after the first message is sent, the server sends an RST section to the client side, and the second message is sent ( The sigpipe signal is generated when the write is called; Note: the client-side test code uses the socket library **/void sighandler (int signo) { if (sigpipe = = Signo) that will be introduced in the next section { cout << "Receive sigpipe =" << sigpipe << Endl; Exit (exit_failure);} } int main () { signal (sigpipe, sighandler); TCPClient Client (8001, "127.0.0.1"); Try { std::string msg; while (Getline (CIN, msg)) { client.send (msg); Client.send (msg); Second time send msg.clear (); Client.receive (msg); Client.receive (msg); cout << msg << Endl; Msg.clear (); } } catch (const socketexception &e) { cerr << e.what () << Endl; }}
the difference between close and shutdown
#include <unistd.h>int close (int fd), #include <sys/socket.h>int shutdown (int sockfd, int);
shutdown |
shut_ RD |
|
shut_wr |
Close the write end |
shut_rdwr |
Read and write closed |
1.close terminated the data transfer. two x direction ;
The shutdown can have the option of terminating data transfer in a direction or terminating data transmission in two directions.
2.shutdown HOW=SHUT_WR (Turn off the write end) guarantees that the peer receives an EOF character (Fin segment), regardless of whether another process has already opened the socket (shutdown does not take a reference count).
and close needs to wait for the socket reference count to be reduced to 0 o'clock to send the fin segment . That is, until all processes have closed the socket.
Sample Analysis:
The client sends the server in sequence: Fin E D C B A, if fin is called close before the client has received ABCDE, then client side will never receive ABCDE, and through the shutdown function, You can choose to close only the sender of the client without shutting down the receiving end, the client side can also receive ABCDE information;
/** Test: Implement the code similar to the above (using Close/shutdown) two ways to implement **/
For full source code, please refer to:
http://download.csdn.net/detail/hanqing280441589/8486517
Note: The best reader needs to have the base of select and readers without select basics can refer to my blog <socket Programming Practices (8) > Related sections
Socket programming Practices (6)--TCP service-side considerations