Non-blocking Connect () __ Network

Source: Internet
Author: User
Tags readable sprintf true true htons

Description: This article applies to the Windows platform, followed by an additional application for Linux platform

Turn from: http://www.cnblogs.com/shiqgfmj/archive/2010/12/29/1919434.html

Non-blocking socket client connect () has been bothering you for the whole afternoon. Because it is non-blocking, it is not possible to know when to connect, regardless of whether the connection is directly returned.
The first thought to find information online, unfortunately not much. So MSDN, finally found a sentence.
With a nonblocking socket, the connection attempt cannot is completed immediately. In the, this function would return socket_error and WSAGetLastError'll resturn Wsaewouldblock. The following list shows the three scenarios that are possible in the:
Use the ' SELECT ' function to determine the completion of the ' connection ' request by checking to the ' if ' is writeabl E.
If the application is using WSAEventSelect to indicate interest in connection events, then the associated event object wil L be signaled indicating this connect operation is complete (successfully or not).
Non-blocking socket connection requests do not complete immediately. At this point, the function returns SOCKET_ERROR and WSAGetLastError () returns WSAEWOULDBLOCK. Here are 2 scenarios for this scenario:
1, use the Select function to check whether this socket can be written to determine whether the connection request is complete;
2. If the program uses WSAEventSelect to show concern for connection events, then the associated event object will be signaled to indicate that the connection operation is complete (success or failure)
The small code is as follows:

Client.c [CPP] View Plain copy Fd_zero (&wtfds);   _timout.tv_sec = 3;   _timout.tv_usec =  0;       msock = socket (af_inet, sock_stream, 0);   toaddr.sin_family = af_inet;   toaddr.sin_port = htons (7000);   Toaddr.sin_addr. S_un. S_ADDR&NBSP;=&NBSP;INET_ADDR ("192.168.1.87");       if  (ioctlsocket (msock,  fionbio, &itemp)  < 0    {       perror (" ioctlsocket error\n ");  }   fd_set (Msock, &wtfds);        Iret = connect (msock,  (sockaddr*) &toaddr, sizeof (toaddr));   if  (! IRet)    {       printf ("connect immediately\n");        char sndMsg[100] = {0};       sprintf (Sndmsg,  "Hello world");       if  (Socket_error == send ( Msock, sndmsg, strlen (sndmsg),  0))        {            perror ("Send error");            return 1;       }       printf (" send success\n ");  }   else if  (iret<0 &&  WSAGetLastError () ==wsaewouldblock)    {       int iRet1 =  Select (0, null, &wtfds, null, &_timout);       if   (iret1 < 0)        {            perror ("connect error\n");            return 1;       }       else if  (!IRET1)        {           perror ("timeout  error\n ");           return 1;        }       else       {            if  (Fd_isset (Msock, &wtfds))             {                printf ("connect success\n");                char sndMsg[100] = {0};                sprintf (sndmsg,  "Hello world");                if  (Socket_error == send (Msock, sndmsg, strlen) ( sndmsg),  0)                {                    perror (" Send error ");                    return 1;                }               printf ("send  success\n ");           }       }   }  


Server.c[CPP] View Plain copy msock = socket (af_inet, sock_stream, 0);   ioctlsocket (msock,  fionbio,  (unsigned long*) &inonbk);   fd_set (Msock, &rdfds);        cltaddr.sin_family = af_inet;   cltaddr.sin_port = htons (7000);    CLTADDR.SIN_ADDR. S_un. s_addr = inaddr_any;   if  (Socket_error == bind msock,  (SOCKADDR*) & Cltaddr, sizeof (CLTADDR))    {       perror ("Bind error");        return 1;  }   if  (socket_error ==  Listen (msock, 5))    {       perror ("Listen error");        return 1;  }       _tim =   Time (NULL);   ltime = localtime (&_tim);   PrintF ("%d:%d:%d\n",  ltime->tm_hour, ltime->tm_min, ltime->tm_sec);        Iret = select (0, &rdfds, null, null, &_timval);   if   (iret < 0)    {       perror ("Accept error");        return 1;  }   else if (iret == 0)    {       perror ("Timeout error");        return 1;  }   else   {       if  (fd_ ISSET (Msock, &rdfds))            printf ("msock  is in rdfds\n ");       else            return 1;                SOCKET clsock = accept (msock,  (sockaddr*) &cltaddr, &ilen);        if  (clsock == invalid_socket)        {           printf ("Clsock is not a valid socket\ n ");           return 1;        }       if  (Fd_isset (Clsock, &rdfds))             printf ("clsock is in rdfds\n");        else           printf ("Clsock is not  in rdfds\n ");       _tim =  time (NULL);       ltime = localtime (&_tim);       printf ("%d: %d:%d\n ",  ltIME-&GT;TM_HOUR,&NBSP;LTIME-&GT;TM_MIN,&NBSP;LTIME-&GT;TM_SEC);       char  recvmsg[100] = {0};       int isize = recv (clsock,  recvmsg, 100, 0);       printf ("from client %s:%s,%d\n"),  inet_ntoa (CLTADDR.SIN_ADDR), Recvmsg,wsagetlasterror ());  }  

The following applies to the Linux platform
Turn from: http://kenby.iteye.com/blog/1183579

Step 1: Set non-blocking, start the connection

To achieve non-blocking Connect, the SOCKFD is first set to non-blocking. So call Connect can return immediately, handling three kinds of cases based on the return value and errno:

(1) If return 0, means connect success.

(2) If the return value is less than 0, errno is einprogress, indicating that the connection establishment has started but has not yet completed. This is the desired result, not the real mistake.

(3) If the return value is less than 0,errno is not einprogress, the connection is wrong.

Step 2: Judge readable and writable

The SOCKFD is then added to the read and write listening collection of Select, and the SOCKFD is determined by select

Can write, handle three kinds of situations:

(1) If the connection is established, the other party has no data to arrive, then SOCKFD is writable

(2) If the connection is established before the Select, and the other's data has arrived, then the SOCKFD is readable and writable.

(3) If the connection occurs incorrectly, SOCKFD is also readable and writable.

To determine whether connect is successful, you have to distinguish between (2) and (3), both of which are SOCKFD

Readable and writable, the distinguishing method is to call getsockopt to check for errors.

Step 3: Check for errors using the getsockopt function

GetSockOpt (SOCKFD, Sol_socket, So_error, &error, &len)

In cases where sockfd are both readable and writable, we use getsockopt to check the connection

Whether there was an error. But there's a portability problem here.

If an error occurs, the implementation of getsockopt originating from Berkeley will be in the variable error

Returns an error, getsockopt itself returns 0, but Solaris lets getsockopt return-1,

and save the error in the errno variable. So in order to judge whether there is a mistake, we have to deal with both of these situations.

Code:[CPP] View Plain copy int conn_nonb (int sockfd, const struct sockaddr_in *saptr,  SOCKLEN_T&NBSP;SALEN,&NBSP;INT&NBSP;NSEC)       {           int flags, n, error, code;           socklen_t len;          fd_set wset;           struct timeval tval;               flags = fcntl (sockfd, f_getfl, 0);           fcntl (Sockfd, f_setfl, flags | o_nonblock) ;               error = 0;           if  (N == connect (sockfd, saptr,  Salen))  == 0)  {              goto done;           } else if  (n < 0 &&  errno != einprogress) {               return  ( -1);          }               /* do whatever we want while the  connect is taking place */               fd_zero (&wset);          fd_set (SOCKFD,  &wset);          tval.tv_sec = nsec;           tval.tv_usec = 0;         &nBsp     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 Solaris implementation getsockopt returns -1,             *   Set Pending error to Errno. berkeley implementation               * getsockopt return 0, pending error back to error.               *  we need to deal with both 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);      }   


about ioctlsocket ()

(Excerpt from: http://www.cnblogs.com/endeavour/archive/2011/11/18/2253529.html)
#include <winsock.h>
This function controls the I/O mode a socket.
int ioctlsocket (SOCKET s, long Cmd,u_long far* ARGP);

Parameters
S
[In] Descriptor identifying a socket.
Cmd
[In] Command to perform on socket s.
Argp
[In, out] Pointer to a parameter for CMD.

Return Value:
If No error occurs, this function returns zero. If An error occurs, a value of Socket_error are returned, and a specific error code can be retrieved by calling Wsagetlaste Rror. The following table shows a list of possible error codes.


U_long mode = 0;
Ioctlsocket (S,fionbio,&mode);
Control is blocking mode.


U_long mode = 1;
Ioctlsocket (S,fionbio,&mode);
Control is non-blocking.


This function can be used for any set of interfaces in any state. It is used to obtain the operation parameters related to the socket interface, and is independent of the specific protocol or communication subsystem. The following commands are supported:
Fionbio: The non-blocking mode of the set interface S is allowed or disallowed. ARGP points to an unsigned long integer. If non-blocking mode is allowed Non-zero, such as blocking non-blocking mode is zero. When you create a nested interface, it is in blocking mode (that is, non-blocking mode is blocked). This is consistent with the BSD socket interface. The Wsaasynselect () function automatically sets the socket interface to non-blocking mode. If a wsaasynselect () operation has been performed on a set of interfaces, any attempt to reset the set interface to blocking mode with ioctlsocket () will fail wsaeinval. In order to reset the socket to blocking mode, the application must first be wsaasynselect () called (ievent parameter 0) to Wsaasynselect ().

Fionread: Determines the amount of data that the sleeve interface s automatically reads. ARGP points to an unsigned long integer that contains the return value of ioctlsocket (). If S is the Socket_stream type, Fionread returns the amount of all the data received in one recv (). This is usually the same amount of data queued in the socket. If S is a sock_dgram type, the Fionread returns the first datagram size queued on the set interface.
Siocatmark: Is it true that all out-of-band data has been read in. This command applies only to the Sock_stream type of socket, and the set of interfaces has been set to receive Out-of-band data (so_oobinline) online. If no out-of-band data is waiting to be read, the operation returns True true. Otherwise, false false is returned, and the next recv () or recvfrom () operation retrieves some or all of the data before "tag". The application can use the Siocatmark action to determine if there is data left. If there is regular data before the "emergency" (out-of-band) data, the data is received sequentially (note that the recv () and recvfrom () operations do not confuse regular and out-of-band data in a single call. ARGP points to a bool, where ioctlsocket () is stored in the return value.

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.