Non-blocking Socket Connection

Source: Internet
Author: User
Tags ip number socket blocking

Solution 1:

Int connect_socket_timeout (INT sockfd, char * dest_host, int port, int timeout)

{

Struct sockaddr_in address;

Struct in_addr inaddr;

Struct hostent * Host;

Int err, Noblock = 1, connect_ OK = 0, begin_time = Time (null );

Log_debug ("connect_socket to % s: % d/N", dest_host, Port );

If (inet_aton (dest_host, & inaddr ))

{

// Log_debug ("inet_aton OK now gethostbyaddr % s/n", dest_host );

Memcpy (& address. sin_addr, & inaddr, sizeof (address. sin_addr ));

}

Else

{

Log_debug ("inet_aton fail now gethostbyname % s/n", dest_host );

Host = gethostbyname (dest_host );

If (! Host ){

/* We can't find an IP number */

Log_error ("error looking up host % s: % d/N", dest_host, errno );

Return-1;

}

Memcpy (& address. sin_addr, host-> h_addr_list [0], sizeof (address. sin_addr ));

}

Address. sin_family = af_inet;

Address. sin_port = htons (port );

/* Take the first IP address associated with this hostname */

IOCTL (sockfd, fionbio, & Noblock );

/** Connect until timeout */

/*

Einprogress A nonblocking socket connection cannot be completed immediately.

Ealready the socket is nonblocking and a previous connection attempt has not been completed.

Eisconn the socket is already connected.

*/

If (connect (sockfd, (struct sockaddr *) & Address, sizeof (Address) <0)

{

Err = errno;

If (Err! = Einprogress)

{

Log_error ("Connect = % d connecting to host % s/n", err, dest_host );

}

Else

{

// Log_notice ("Connect pending, return % d/N", err );

While (1)/* Is noblocking connect, check it until OK or timeout */

{

Connect (sockfd, (struct sockaddr *) & Address, sizeof (Address ));

Err = errno;

Switch (ERR)

{

Case eisconn:/* connect OK */

Connect_ OK = 1;

Break;

Case ealready:/* is connecting, need to check again */

// Log_info ("Connect again return ealready check again.../N ");

Usleep (50000 );

Break;

// Default:/* failed, retry again? */

Log_error ("Connect fail err = % d/N", err );

// Connect_ OK =-1;

// Break;

}

If (connect_ OK = 1)

{

// Log_info ("Connect OK try time = % d/N", (Time (null)-begin_time ));

Break;

}

If (connect_ OK =-1)

{

Log_notice ("Connect failed try time = % d/N", (Time (null)-begin_time ));

Break;

}

If (timeout> 0) & (Time (null)-begin_time)> timeout ))

{

Log_notice ("Connect failed, timeout % d seconds/N", (Time (null)-begin_time ));

Break;

}

}

}

}

Else/* connect successful immediately */

{

// Log_info ("Connect immediate success to host % s/n", dest_host );

Connect_ OK = 1;

}

/** End of try connect */

Return (connect_ OK = 1 )? Sockfd:-1 );

}

Solution 2:

In addition, the application of select in asynchronous (non-blocking) connect was just started with socket programming.

I have always used blocking-type connect. The problem with non-blocking connect is that proxy scan was used at the time.

However

Through online communication with netizens and related FAQs, I finally learned how to solve this problem.

Using select can solve this problem well. The general process is as follows:

1. Set the opened socket to non-blocking. You can use fcntl (socket, f_setfl, o_ndelay)

(Some systems can also use fnedlay ).

2. Send the Connect call. At this time,-1 is returned, but errno is set to einprogress, meaning that connect is still

The process is not completed yet.

3. Set the opened socket to the monitored writable (note that it is not readable) file set and use select for monitoring,

If it can be written, use

Getsockopt (socket, sol_socket, so_error, & error, sizeof (INT ));

To get the error value. If it is zero, connect is successful.

In many UNIX versions of proxyscan programs, you can see similar processes, in addition to the essence of Solaris

Area-> there is a general connect module with timeout parameters in programming skills.

We know that sockets in the default state are blocked, which means that when a set of interface calls cannot be completed immediately, the process will enter the sleep state and wait until the operation is completed. For some applications
Timely and controllable customer response, and blocking may lead to a long period of time, the connection does not respond. The main operations that cause socket blocking include Recv, send, accept,
Connect.

The following uses connect as an example to describe how non-blocking connect works. When a TCP socket is set to non-blocking, call connect and immediately return
Einprocess error. However, the TCP three-way handshake continues. We will use the select function to check whether the connection is established successfully. The following three functions are used to establish non-blocking CONNECT:
Path:

1. you can do other things when the system performs a three-way handshake. During this period, you can do whatever you want.

2. This technology can be used to establish multiple connections at the same time, which is common in Web applications.

3. It can shorten the connect timeout time. In most implementations, the connect timeout is between 75 seconds and several minutes?

Although non-blocking conncet implementation is not complex, we must pay attention to the following details:

* Even if the socket is not blocked, if the Connected Server is on the same host, connect is usually established immediately. (Connect returns 0 instead of einprocess)

* When the connection is established successfully, the description word becomes writable.

* When a connection error occurs, the description is readable and writable.

Routine: defines a non-blocking connect function connect_nonb

Int connect_nonb (INT sockfd, const Sa * saptr, socklen_t Salen, int nsec)

{

Int flags, N, error;

Socklen_t Len;

Fd_set rset, Wset;

Struct timeval tval;

// Obtain the attributes of the current socket and set the noblocking attribute

Flags = fcntl (sockfd, f_getfl, 0 );

Fcntl (sockfd, f_setfl, flags | o_noblock );

Errno = 0;

If (n = connect (sockfd, saptr, salen) <0)

If (errno! = Einprogress)

Return (-1 );

// You can perform any other operations.

If (n = 0)

Goto done; // generally called by the same host, 0 is returned.

Fd_zero (& rset );

Fd_set (sockfd, & rset );

Wset = rset; // block copy will be performed here

Tval. TV _sec = nsec;

Tval. TV _usec = 0;

// If nsec is 0, the default timeout time is used, that is, its structure pointer is null.

// If the time in the tval structure is 0, it indicates that no waiting is performed and immediate response is returned.

If (n = select (sockfd + 1, & rset, & West, null, nsec? Tval: NULL) = 0 ){

Close (sockfd );

Errno = etimeout;

Return (-1 );

}

If (fd_isset (sockfd, & rset) | fd_isset (sockfd, & West )){

Len = sizeof (error );

// If the connection is successful, 0 is returned for this call.

If (getsockopt (sockfd, sol_socket, so_error, & error, & Len) <0)

Return (-1 );

}

Else err_quit ("select error: sockfd not set ");

Done:

Fcntl (sockfd, f_setfl, flags); // restore socket attributes

If (error ){

Close (sockfd );

Errno = error;

Return (-1 );

}

Return (0 );

}

Note:

* If the connection has been established successfully before the Select call and data is sent, the socket can be read and writable, which is the same as when the connection fails. Therefore, we must use getsockopt to check the socket status.

* If we are not sure that the socket can be written successfully, we can use the following call:

(1) Call getpeername. If the call fails, enotconn is returned, indicating that the connection fails.

(2) Call read. The length parameter is 0. If read fails, connect fails.

(3) Call connect again. If the error is eisconn, the socket has been established and the connection is successful.

* If you call connect on a blocked socket, It is interrupted before the TCP three-way handshake. If connect is not automatically restarted, eintr is returned. However, we cannot call connect to wait until the connection is complete. This will return eaddrinuse. At this time, we must call select, which is the same as the non-blocking method.

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.