Step 1: Set non-blocking, start the connection to implement non-blocking connect, first set the SOCKFD to non-blocking. This calls connect to return immediately, handling three cases based on the return value and errno: (1) If you return0, indicating that connect succeeded. (2) If the return value is less than0, errno is einprogress, which indicates that the connection establishment has started but has not yet been completed. This is the desired result, not a real error. (3if the return value is less than 0,errno is not einprogress, the connection is faulted. Step 2: Judge readable and writable and add SOCKFDSelectRead-write listening set, throughSelectdetermine if SOCKFD can be written and handle three situations: (1If the connection is established and no data arrives, then the SOCKFD is writable (2) If theSelectbefore, the connection is established, and the data of the other party has arrived, then the SOCKFD is readable and writable. (3SOCKFD is also readable and writable if there is an error in the connection. To determine if connect is successful, make a difference (2and3In both cases, the SOCKFD is readable and writable, and the way to differentiate it is to call getsockopt to check for errors. Step 3: Use the GetSockOpt function to check for error getsockopt (SOCKFD, Sol_socket, So_error,&error, &Len) In cases where sockfd are both readable and writable, we use getsockopt to check the connection for errors. But there's a portability problem here. If an error occurs, the implementation of the getsockopt originating from Berkeley returns an error in the variable error, getsockopt itself returns 0, but Solaris lets getsockopt return-1, and save the error in the errno variable. So when judging whether there are errors, you should deal with both cases. Code: C Code Collection CodeintCONN_NONB (intSOCKFD,Const structSockaddr_in *saptr, socklen_t Salen,intnsec) { intflags, n, error, code; Socklen_t Len; Fd_set Wset; structTimeval Tval; Flags= Fcntl (SOCKFD, F_GETFL,0); Fcntl (SOCKFD, F_SETFL, Flags|O_nonblock); Error=0; if(n = = Connect (SOCKFD, saptr, salen) = =0) { GotoDone ; } Else if(N <0&& errno! =einprogress) { return(-1); } /*Do whatever we want while the connect are taking place*/Fd_zero (&wset); Fd_set (SOCKFD,&wset); Tval.tv_sec=nsec; Tval.tv_usec=0; if((n =Select(sockfd+1, NULL, &wset, NULL, Nsec? &tval:null)) = =0) {close (SOCKFD); /*Timeout*/errno=etimedout; return(-1); } if(Fd_isset (SOCKFD, &wset)) {Len=sizeof(Error); Code= GetSockOpt (SOCKFD, Sol_socket, So_error, &error, &Len); /*If an error occurs, the getsockopt of the Solaris implementation returns-1, * Pending error is set to errno. Berkeley implementation of * GetSockOpt returns 0, pending error returned to error. * We need to deal with both of these situations*/ if(Code <0||error) {Close (SOCKFD); if(Error) errno=error; return(-1); } } Else{fprintf (stderr,"Select ERROR:SOCKFD Not set"); Exit (0); } done:fcntl (SOCKFD, F_SETFL, flags); /*Restore file Status flags*/ return(0); }
Non-blocking Connect