We do some more work for the client's writing.
This time we use non-blocking IO to implement the Connect function.
int Connect (intconststruct sockaddr *addr, socklen_t Addrlen);
Non-blocking IO has the following uses:
1. The process of three handshake is born, and other things are handled.
2. Use this to establish multiple connections at the same time.
3. To implement the Timeout connect function, the connect implemented in this section can specify time and count as error handling after timeout.
In blocking IO, the call to connect is generally blocked until the connection is determined to succeed or fail.
In non-blocking io, connect tends to return immediately, when Connect has two results.
One is the success of the connection
The second is to return -1,errno to einprogress, this is generally due to network delay, so the connection can not be established immediately, we need to use poll to monitor the SOCKFD.
So next we need to register SOCKFD's write event to poll.
The second volume of TCP/IP details indicates some of the following rules:
SOCKFD can be written when the connection is established.
When an error is encountered, the SOCKFD is both readable and writable.
We set a time-out period when poll returns, and if SOCKFD is writable, there are two things at this time:
One is that the connection does build up successfully
Second, the connection error occurred
We need some means to tell if something is wrong.
Here we use the socket option, the detection is So_error, the code is as follows:
intGet_sockfd_error (intsockfd) { interr; socklen_t Socklen=sizeof(ERR); if(GetSockOpt (SOCKFD, Sol_socket, So_error, &err, &socklen) = =-1) Err_exit ("Getsock_error Error"); if(Err = =0) return 0;//No Errors Else returnerr;}
Returns 0 if SOCKFD is error-free, otherwise an error code is returned.
In the implementation of non-blocking connect, we usually need to set FD to non-blocking and then set it back to block. This is done in order to meet the blocking and non-blocking requirements.
Because in blocking IO, there are times when non-blocking connect is used.
The implementation code is as follows:
intNonblocking_connect (intSOCKFD,Const Char*des_host, uint16_t Des_port,intTimeout) { if(Des_host = =NULL) {fprintf (stderr,"Des_host can null\n"); Exit (Exit_failure); } SAI servaddr; memset (&SERVADDR,0,sizeofservaddr); Servaddr.sin_family=af_inet; Servaddr.sin_port=htons (Des_port); if(Inet_aton (des_host, &servaddr.sin_addr) = =0) { //DNS//struct hostent *gethostbyname (const char *name); structHostent *HP =gethostbyname (des_host); if(HP = =NULL) Err_exit ("gethostbyname"); Servaddr.sin_addr= *(structin_addr*) hp->h_addr; } //set to non-blockingActivate_nonblock (SOCKFD); //Connect will return immediately intret = Connect (SOCKFD, (sa*) &servaddr,sizeofservaddr); if(ret = =-1) { if(errno! = einprogress)//Connection FailedErr_exit ("Connect Error"); structPOLLFD pfd[1]; pfd[0].FD =SOCKFD; pfd[0].events =pollout; RET= Poll (PFD,1, timeout); if(ret = =0) {errno=etimedout; RET= -1;//connection timed out, this time determined to be a failure } //sockfd writable, check socket options at this time to see if an error occurred Else if(ret = =1&& pfd[0].revents & (Pollout |Pollwrband)) { interr; //Check for SOCKFD errors if(Err =Get_sockfd_error (SOCKFD))) {errno=err; return-1; } } } //re-set to blockedDeactivate_nonblock (SOCKFD); returnret;}
Readers can test themselves.
The following section implements the client using non-blocking connect.
Linux non-blocking IO (quad) Implementation of connect in non-blocking IO