Windows performs I/O operations in non-blocking and blocking modes. In blocking mode, only one client's request can be executed on the port of an IP address to process the next request. Requests are queued and executed in sequence. This is synchronization. Asynchronous means that two or more requests are sent at the same time, and the server corresponds to multiple clients at the same time. They are executed in parallel.
In blocking mode and single thread, if an I/O operation is blocked, the entire program will be blocked. If the conditions are not met, the program will be locked forever.
The following code creates a set of characters and sets it to non-blocking mode.
Socket s; usigned long cmd; int nstatus; S = socket (af_inet, sock_stream, 0); nstatus = ioctlsocket (S, fiobio, & cmd); If (nstatus = sock_error) {// failed to set non-blocking mode}
After a socket is set to non-locked and blocked, Windows API calls will return immediately. In most cases, these calls will fail, and the operation returned by the wsaewouldblock error identification request will not be completed during the call, since the non-lock call will frequently return the wsaewouldblock error, the programmer needs to constantly check when the function returns code half a socket for read/write, in order to avoid the trouble, Winsock provides several different Socket I/O models to manage I/O. Including select, wsaeasyncselect, wsaeventselect, overlapped, and completion)
The select model is used to prevent locking in the socket in blocking mode and prevent repeated wsaewouldblock errors in the non-blocking socket.
The Select () function can determine the status of one or more sockets, determine whether data exists on the socket, or whether data can be written to a socket. It not only prevents application programs from being blocked after an I/O operation when the socket is in blocking mode, but also prevents wsaewouldblock errors when the socket is in non-locked mode.
Int select (INT NFDs, // negligible, compatible with the Berkeley socket fd_set * readfds, // pointer to the socket group waiting for readability check fd_set * writefds, // The pointer fd_set * destination TFDs to the socket group waiting for the writability check, // the pointer const struct timeval * timeout to the socket group waiting for the error check. // It is the timeval structure data, used to specify the maximum waiting time for select (), and null for blocking operations)
At least one of the three fd_set parameters is not null. In any set that is not empty, it must contain at least one socket handle; otherwise, select () the function has nothing to wait.
When a successful response is returned, the fd_set structure contains a subset of sockets that meet certain conditions, and select () returns the number of sockets that meet the conditions. If the time exceeds the time specified by timeval, 0 is returned. If the call fails, socket_error is returned.
Struct timeval {long TV _sec; // Second Long TV _usec; // millisecond}
Set the timeout value to (0, 0 ). Select () returns immediately, allowing the application to perform "Round Robin" on the Select Operation ". This setting should be avoided for performance considerations.
Winsock provides the fd_setsize variable to determine the maximum number of socket descriptions in a set. The default value is 64 bits. You can use # define fd_setsize to change this value before including Winsock. h.
Fd_clr (S, * Set): removes socket s from the set.
Fd_isset (S, * Set): If S is a member of the set, it is non-zero; otherwise, it is zero.
Fd_set (S, * Set): Add socket s to the set
Fd_zero (* Set): initializes the set to null.
To test whether a socket is "readable"
(1) Add the socket to the readfds collection
fd_set fdread;
FD_ZERO(&fdread);
FD_SET(s,&fdread);
(2) Call the select () function
select(0,&fdread,NULL,NULL,NULL);
(3) Wait for select () to return. If the call succeeds, it determines whether the socket is still a member of the readfds set. If the answer is yes, it indicates that the socket is "readable ", reads data from it immediately.
if(FD_ISSET(s,&fdread))
{
// Read data from the socket
}