Summary of select device timeout usage

Source: Internet
Author: User
Tags set socket socket blocking socket connect

Summary of select device timeout usage

Currently, the common method for setting SOCKET connect timeout on each platform is to use select (). The specific method is as follows:

1. Establish socket;

2. Set the socket to non-blocking mode;

3. Call connect ();

4. Use select () to check whether the socket descriptor is writable;

5. Determine the connect () result based on the result returned by select;

6. set socket back to blocking mode.

 

Select is used to monitor the status changes of a certain or some handles and perform I/O multiplexing.

The prototype of the select function is as follows:

Int select (INT NFDs, fd_set * readfds, fd_set * writefds, fd_set * limit TFDs, struct timeval * timeout );

NDfS: the number of file handles monitored by the SELECT statement, depending on the number of files opened in the process. It is generally set to the maximum file number plus one in each file to be monitored.
Readfds: a collection of readable file handles monitored by select.
Writefds: a set of writable file handles monitored by select.
Except TFDs: a collection of abnormal file handles monitored by select.
Timeout: the timeout end time of this select () operation.

When the image files in readfds or writefds are readable, writable, or time-out, this select () operation ends and returns. Programmers can use the macros provided by a set of systems to determine which file is readable or writable at the end of select. Readfds is particularly useful for socket programming. Several related macros are explained as follows:
Fd_zero (fd_set * fdset): clears the contact between fdset and all file handles.
Fd_set (int fd, fd_set * fdset): Establishes the connection between the file handle FD and fdset.
Fd_clr (int fd, fd_set * fdset): clears the contact between the file handle FD and fdset.
Fd_isset (int fd, fdset * fdset): Check whether the file handle FD associated with fdset is readable or not.> 0 indicates that the file handle FD can be read or written.

 

The last timeout parameter of the function is obviously a timeout value. Its type is struct timeval *, which is a pointer to a variable in the struct timeval structure, so we need to declare a struct timeval TV in the program; then pass the TV variable address & TV to the select function. The structure of struct timeval is as follows:

Struct timeval

{

Long TV _sec;/* seconds */

Long TV _usec;/* microseconds */

};
 

The three parameters 2nd, 3, and 4 are of the same type: fd_set *, that is, we need to declare several fd_set variables in the program, such as rdfds, wtfds, exfds, then, pass the address & rdfds, & wtfds, & exfds of the variable to the select function.

These three parameters are a collection of handles. The first rdfds is used to save such a handle: When the handle status changes to readable, the system will tell the select function to return the handle, similarly, the second wtfds indicates that the system will tell the select function to return a result when the handle state is changed to writable. Similarly, the third parameter exfds is a special case, that is, when a special case occurs on the handle, the system will tell the select function to return. In special cases, for example, the other Party sends emergency data through a socket handle. If we only want to check whether data in a socket is readable, we can:

Fd_set rdfds;/* declare an fd_set set to save the socket handle to be detected */

Struct timeval TV;/* declare a time variable to save the time */

Int ret;/* Save the returned value */

Fd_zero (& rdfds);/* clears the set before using the select function */

Fd_set (socket, & rdfds);/* Add the socket of the handle to be detected to the Set */

 

TV. TV _sec = 1;

TV. TV _usec = 500;/* set the maximum waiting time for select to 1 second plus 500 microseconds */

 

Ret = select (socket + 1, & rdfds, null, null, & TV);/* checks whether the handle set in rdfds has readable information */

If (Ret <0)

Perror ("select");/* This indicates that the select function has an error */

Else if (ret = 0)

Printf ("time-out/N");/* indicates that the status of the socket has not changed within the time range of 1 second plus 500 milliseconds */

Else

{/* Indicates that the waiting time is less than 1 second plus 500 milliseconds, and the socket status has changed */

Printf ("ret = % d/N", RET);/* The returned value of RET records the number of State-changing handles. Since we only monitor the socket handle, therefore, RET must be 1. If multiple handles change at the same time, the total number of handles is returned */

/* Here we should read data from the socket handle, because the select function has told us that the handle contains data readable */

If (fd_isset (socket, & rdfds) {/* first checks whether the handle monitored outside the socket is actually readable */

/* Read data in the socket handle */

Recv (...);

}

}
 

Note that the first parameter of the select function is the maximum value of all the handle values that are added to the set. For example, we have created three handles:

 

Int SA, Sb, SC;

Sa = socket (...);/* create three handles respectively and connect them to the server */

Connect (SA ,...);

SB = socket (...);

Connect (SB ,...);

SC = socket (...);

Connect (SC ,...);

Fd_set (SA, & rdfds);/* add three handles to the read monitoring set respectively */

Fd_set (SB, & rdfds );

Fd_set (SC, & rdfds );
 

Before using the select function, you must find the maximum value among the three handles. We generally define a variable to save the maximum value and obtain the maximum socket value as follows:

Int maxfd = 0;

If (Sa> maxfd)

Maxfd = sa;

If (Sb> maxfd)

Maxfd = Sb;

If (SC> maxfd)

Maxfd = SC;
 

Then, call the select function:

Ret = select (maxfd + 1, & rdfds, null, null, & TV);/* Add 1 to the maximum value */
 

In the same way, if we want to check whether the user enters the input by the keyboard, we should put the handle of the standard input 0 in the SELECT statement to check, as shown below:

Fd_zero (& rdfds );

Fd_set (0, & rdfds );

TV. TV _sec = 1;

TV. TV _usec = 0;

Ret = select (1, & rdfds, null, null, & TV);/* Note that the maximum value must be 1 */

If (Ret <0)

Perror ("select");/* Error */

Else if (ret = 0)

Printf ("timeout/N");/* the user does not press the keyboard during the specified time TV */

Else {/* the user has a keyboard to read the user's input */

Scanf ("% s", Buf );}

 

 

 

 

 

How to Set connection timeout in Linux:

In general, connect () will not return until the client's ACK message for SYN messages arrives. One way to make connect () call timeout mechanism is to make the socket a non-blocking Socket body, and then use select () to wait for it to complete.
S = socket (af_inet, sock_stream, 0 );
// Obtain the socket flag below
If (flags = fcntl (S, f_getfl, 0) <0 ){
// Handle errors
}

// Set the socket below to be non-blocking
If (fcntl (S, f_setfl, flags | o_nonblock) <0 ){
// Handle errors
}

If (retcode = connect (S, (struct sockaddr *) & peer, sizeof (PEER ))&&
Errno! = Einprogress ){
// Because the socket is set to nonblock, normally, the connection returns
// It is not previously created, so it will return the einprogress error. If it returns
// Handle any other errors
}

If (0 = retcode) {// If connect () returns 0, the connection is established
// Resume the socket blocking status below
If (fcntl (S, f_setfl, flags) <0 ){
// Handle errors
}

// The following code is executed after the connection is successful

Exit (0)
}

(To send/Recv messages to the device, you only need to modify the corresponding value from this point. This parameter is not required)
Fd_zero (& rdevents );
Fd_set (S, & rdevents); // Add the previous socket to the read set
Wrevents = rdevents; // write set
Exevents = rdevents; // exception set

TV. TV _sec = 5; // set the time to 5 seconds
TV _ TV _usec = 0;

Retcode = select (S + 1, & rdevents, & wrevents, & exevents, & TV );
If (retcode <0) {// select Return Error ???
// Handle errors
}
Else if (0 = retcode) {// select time-out ???
// Timeout Processing
}
Esle {
// The socket is ready
If (! Fd_isset (S, & rdevents )&&! Fd_isset (S, & wrevents )){
// Connect () failed and handle the error
}

If (getsockopt (S, sol_socket, so_error, & err, & Len) <0 ){
// Getsockopt () failed to handle the error
}

If (Err! = 0 ){
// Connect () failed and handle the error
}
(Send/Recv times out until now, return the send ()/Recv () function)

// Connect () returns the correct result here
// Resume the socket blocking status below
If (fcntl (S, f_setfl, flags) <0 ){
// Handle errors
}

// The following code is executed after the connection is successful

Exit (0)

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.