Socket programming Practice under Linux (iv) TCP server-side optimizations and common functions

Source: Internet
Author: User

Zombie Process processing under concurrent

With only one process connected, we can handle the zombie process in two ways:

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);  }  
So what if multiple clients are shutting down at the same time in a multi-process state?


We can test with the following client code:

/** 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 (a);  }  
At this time because the signal arrives at the same time, and sigchld is unreliable signal, does not support queuing, will leave a considerable part of the zombie process


Workaround:

Using the Waitpid function of the loop, you can dispose of the zombie processes left by all the child processes

void Sighandler (int signo)  {while      (Waitpid ( -1, NULL, Wnohang) > 0)          ;  }//pid=-1 waits for any child process, equivalent to wait (). Wnohang if the PID-specified child process does not end, the Waitpid () function returns 0, not waiting. If it ends, the ID of the child process is returned.
API for address queries

 #include <sys/socket.h> int getsockname (int sockfd, struct sockaddr *addr, socklen_t *addrlen); Gets the local addr structure 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, socklen_t len, int  Type);  struct hostent *gethostent (void); 
Hostent structure  struct hostent  {      char  *h_name;            /* Official name of host */      char **h_aliases;         /* Alias list */      int    h_addrtype;        /* Host Address type */      int    h_length;          /* Length of Address */      char **h_addr_list;       /* List of addresses */  }  

The timing of these two function calls is important, otherwise the correct address and port cannot be obtained:

Tcp

For a server, you can call getsockname after bind to get the local address and port, although that doesn't make much sense. Getpeername is only called after the link is established, otherwise the address and port can not be correctly obtained, so his parameter description word is usually a link descriptor rather than a listener interface descriptor.

For the client, the kernel will not allocate IP and port at the time of calling the socket, the call getsockname will not get the correct port and address (of course the link is not established more unlikely to call Getpeername), of course, if bind is called You can use getsockname later. Want to correct to the other side of the address (the general client does not need this feature), you must after the link is established, the same link after the establishment, the client address and port is already specified, this is the time to call GetSockName.

Udp

UDP is divided into links and no links 2 kinds (this to UDP and connect can find relevant content)

UDP without a link cannot call Getpeername, but can call getsockname, like TCP, where his address and port are not specified at the time of the call to the socket, but after the first call to the SendTo function

Already linked UDP, after calling connect, these 2 functions are available (again, Getpeername doesn't make much sense.) If you do not know the address and port of the other, it is not possible to call connect).


get all IP for this machine:

/** gets 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;  }  
Brief description of TCP 11 states



1. When client and server connections are established, both parties are in established (established) state


2. For time_wait status See http://www.mamicode.com/info-detail-190400.html

3.the 11th state of the 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. (Because the active closed side will enter the TIME_WAIT state, both sides simultaneously actively close, then all enter)

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);

Sigpipe, although has received to FIN, but I can also send data to each other; if the other person does not already exist, thenTCPwill be reset,TCPprotocol Stack SendRSTsegment,receivedRSTafter, then proceedWritewill produceSigpipesignal.

In fact, it's good to understand: TCP Can be thought of as a full-duplex pipe, the read-side signal does not exist, if you write to the pipe will cause Sigippe the generation of signals, The process is to ignore this signal can be, in fact, according to the rules of the pipeline.

When we were testing,in theClientsend each message two times,whenServerAfter the end is closedServerThe end will send aFINsub-section toClientEnd, after the first message is sent, the ServerThe end will send aRSTsub-section toClientThe second message is sent.(calledwrite)when, will produceSigpipeSignal.

The difference between the close and shutdown functions

#include <unistd.h>  int close (int fd);    #include <sys/socket.h>  int shutdown (int sockfd, int how);  

How parameters for shutdown

Shut_rd

Close the Read end

Shut_wr

Close the Write end

Shut_rdwr

Both read and write off


Close terminates two directions of data transfer, shutdown can selectively terminate data transfer in a certain direction or terminate data transfer in two directions

SHUTDOWM How=1 can guarantee that the peer receives an EOF character, regardless of whether other processes have opened the socket.

Close does not guarantee that it will be sent until the socket reference count is reduced to 0. This means that all processes are closed with sockets.

Call Close function, which may result in the loss of data when a full-duplex pipe has not been shot back to the client, for example

FIN D C B A

A B C D----lost, closed Close

Close exactly means that when the socket reference count is reduced to 0 , the FIN is sent

int conn;conn=accept (sock,null,null);p id_t pid=fork (), if (pid==-1)   err_exit ("fork"), if (pid==0) {close (sock);// Communication Close (conn); The fin segment is then sent to the other side (since this time the Conn reference count is reduced to 0)}else if (pid>0)   









Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Socket programming Practice under Linux (iv) TCP server-side optimizations and common functions

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.