The Select () mechanism provides a FD_SET data structure, which is actually a long array in which each element of an array can be contacted with an open file handle (whether it is a socket handle or another file or a named pipe or device handle), and the work of establishing a connection is done by the programmer. When select () is called, the kernel modifies the contents of the Fe_set based on the IO state, thereby notifying the process that executed the select () which socket or file is readable.
Multi-port Multiplexing function Select to set the number of ports to listen first before calling, Fd_zero is the port set to be emptied, and Fd_set is the set port set.
The Select () function is often used to listen to multiple server-side sockets with a single process.
Sometimes select () is also used as a delay function. The sleep () delay releases the Cpu,select (), which can be delayed with CPU usage.
The Select () function is primarily based on the Fd_set type. Fd_set (which is important so first) is a set of file description words (FD), which is represented by a single FD (described below), for the Fd_set type by the following four macros:
Fd_set set;
Fd_zero (&set); /* Zeroing set so that no fd*/is included in the collection
Fd_set (FD, &set); /* Add FD to set set */
FD_CLR (FD, &set); /* Clear FD from set collection */
Fd_isset (FD, &set); /* Test if FD is in set set */
In the past, a fd_set usually can only contain <32 fd (file descriptor), because fd_set actually only used a 32-bit vector to represent FD; The UNIX system now typically defines the constant fd_setsize in the header file <sys/select.h>, which is the number of descriptive words for the data type Fd_set, which is usually 1024, which can represent the FD of <1024. Based on the fd_set bit vector implementation, we can re-understand the operation of the Fd_set four macros:
Fd_set set;
Fd_zero (&set); /* Set the set to 00000000*/all positions 0, if set is 8 bits in memory
Fd_set (0, &set); /* Sets the No. 0 position of Set 1, if set is originally 00000000, then now becomes 100000000, so that the Fd==1 file descriptor is added to the set */
FD_CLR (4, &set); /* Sets the 4th position of set 0, if set is originally 10001000, then now becomes 10000000, so that the fd==4 file descriptor is removed from the set */
Fd_isset (5, &set); /* Tests whether the 5th bit of set is 1, if the original set is 10000100, returns nonzero, indicating that the Fd==5 file descriptor is in set, otherwise returns 0*/
Note: The maximum value of FD must be <fd_setsize.
The interface of the Select function is relatively straightforward:
int select (int Nfds, fd_set* readset, fd_set* writeset, fe_set* exceptset, struct timeval* timeout);
Function:
Test the specified FD-readable? Can write? Have abnormal conditions pending?
Parameters:
Nfds: The number of file descriptors that need to be checked (that is, check to Fd_set), the value should be greater than the maximum FD value contained in the three groups of Fd_set, generally set to three groups fd_set the maximum FD values plus 1 (for example, in Readset, Writeset, The Exceptset contains the largest FD of 5, then nfds=6, since FD is starting from 0). This value is set to increase efficiency so that the function does not have to check all 1024 bits of fd_set.
Readset: A set of file description words used to check readability.
Writeset: A set of file descriptors used to check for the writable character.
Exceptset: A file description word that is used to check for abnormal conditions. (Note: The error is not included in the exception condition)
Timeout: There are three possible types:
1. Timeout = NULL (block: Returned until an FD bit is set to 1 function)
2. Timeout points to a struct that is set to a nonzero time (waiting for a fixed time: There is an FD bit set to 1 or the time is exhausted, the function returns)
3. Timeout points to the structure, the time is set to 0 (non-blocking: function checks each FD immediately after the return)
Return value: Returns the total number of FD that corresponds to a bit that is still 1.
Remark:
All three groups of Fd_set will have some FD positions of 0, only those that are readable, writable, and have abnormal conditions pending the FD bit remains 1.
The process of using the Select function is generally:
Call the macro Fd_zero the specified fd_set, then call the macro Fd_set will need to test the FD join Fd_set, then call the function Select Test Fd_set all FD, and finally use the macro fd_isset to check that an FD after the function select Call, Whether the corresponding bit is still 1.
Here is an example that tests the readability of a single file description word:
int isready (int fd)
{
int RC;
Fd_set FDS;
struct Timeval TV;
Fd_zero (&fds);
Fd_set (FD, &fds);
tv.tv_sec = tv.tv_usec = 0;
rc = Select (fd+1, &fds, NULL, NULL, &TV);
if (rc<0)//error
return-1;
Return Fd_isset (FD, &fds)? 1:0;
}
Here's a more complex application:
This code specifies the readable legibility of the description of the test socket, because the socket uses the FD
Unit32 socketwait (tsocket* s, BOOL Rd, BOOL WR, Unit32 Timems)
{
Fd_set RfDs, Wfds;
#ifdef _WIN32
Timeval TV;
#else
struct Timeval TV;
#endif/*_win32*/
Fd_zero (&rfds);
Fd_zero (&wfds);
if (RD)//true
Fd_set (*s, &rfds); Add a descriptive word to test
if (WR)
Fd_set (*s, &wfds);
Tv.tv_sec = timems/1000; Seconds
Tv.tv_usec = timems%1000; Ms
for (;;)//If errno==eintr, test the readability of the buffer repeatedly
Switch (select (*s) +1, &fds, &wfds, NULL, (timems==time_infinite? NULL:&TV))//test whether the socket interface receive buffer has data readable within the specified time
{
0--Timeout, -1--error
Case 0:/*time out*/
return 0;
Case ( -1):/*socket error*/
if (SocketError () ==eintr)
Break
return 0; Wrong, but not eintr.
Default
if (Fd_isset (*s, &rfds))//If S is a member of FDS returns non 0, otherwise returns 0
return 1;
if (Fd_isset (*s, &wfds))
Rerun 2;
return 0;
};
}
Linux fd_set mechanism