The select model is the most common I/O model in Winsock. The core is to use the select function to manage I/O! The select function is used to determine whether data on a socket is readable or whether data can be written to a socket to prevent the program from being in blocking mode, during an I/O call (such as send, Recv, and accept), the system is forced to enter the "locked" State. It also prevents wsaewouldblock errors when the socket is in non-blocking mode.
Select function prototype:
Int select (
Int NFDs, // input parameter, ignore
Fd_set far * readfds, // check readability
Fd_set far * writefds, // check writability
Fd_set far * contains TFDs, // exception data
Const struct timeval far * timeout // The longest wait time for this select call
);
Return Value of the function. After the select () function is called, the return value is an interface descriptor that is ready and included in the fd_set structure. That is, it must modify the set, delete the APIs that cannot be specified. If a timeout occurs, 0 is returned. If an error occurs, socket_error is returned. The application can obtain the error code through wsagetlasterror.
Fd_set is a structure type specifier, which represents a set of specific interfaces. Its definition is as follows:
Typedef struct fd_set {
U_int fd_count;/* how many are set? */
Socket fd_array [fd_setsize];/* an array of sockets */
} Fd_set;
Timeval is a structure type, which is defined as follows:
Struct timeval {
Long TV _sec;/* seconds */
Long TV _usec;/* and microseconds */
};
If the time-out value is set to (0, 0), select returns immediately. This setting should be avoided for performance considerations.
The following is a program for testing the select () function. One server has two clients.
The following are the server programs:
# Define fd_setsize 500
# Include <winsock2.h>
# Pragma comment (Lib, "ws2_32 ")
# Include <stdio. h>
Int main ()
{
Printf ("server program... \ n ");
// ------ ① Load ----------
Wsadata;
If (wsastartup (makeword (2, 2), & wsadata )! = 0)
{
Printf ("wsastartup failed, error = [% d] \ n", wsagetlasterror ());
Return 1;
}
Else
Printf ("① loaded successfully \ n ");
// ------- ② Create a streaming socket ------------
Socket S = socket (af_inet, sock_stream, 0 );
If (S = invalid_socket)
{
Printf ("socket () failed, error = [% d] \ n", wsagetlasterror ());
Return 1;
}
Else
Printf ("② the listener set interface has been created: [% d] \ n", S );
// Place the set interface s in "non-blocking mode"
U_long U1 = 1;
Ioctlsocket (S, fionbio, (u_long *) & U1 );
// ----------- ③ Bind the local address ---------------------
Struct sockaddr_in sadd;
Sadd. sin_family = af_inet;
Sadd. sin_port = htons (5555 );
Sadd. sin_addr.s_un.s_addr = inet_addr ("192.168.31.1 ");
If (BIND (S, (sockaddr *) & sadd, sizeof (sadd) = socket_error)
{
Printf ("BIND () failed, error = [% d] \ n", wsagetlasterror ());
Return 1;
}
Else
Printf ("③ binding successful, local IP Address: [% s], Port: [% d] \ n", inet_ntoa (sadd. sin_addr), ntohs (sadd. sin_port ));
// -------------- ④ Enter the listening status -----------------
If (Listen (s, 3) = socket_error)
{
Printf ("Listen failed, error = [% d] \ n", wsagetlasterror ());
Return 1;
}
Else
Printf ("④ entering the listening status \ n ");
// -------------- ⑤ Select -------------------
// Preparations
Int x = 1;
Timeval TV;
TV. TV _sec = 20;
TV. TV _usec = 0;
Fd_set socket_jh01;
Fd_zero (& socket_jh01 );
Fd_set (S, & socket_jh01 );
Fd_set socket_jh02;
Fd_zero (& socket_jh02 );
While (true)
{
Socket_jh02 = socket_jh01;
Int sock_sum = select (0, & socket_jh02, null, null, & TV );
// ------ Success
If (sock_sum> 0)
{
For (INT I = 0; I <(INT) socket_jh02.fd_count; I ++)
{
If (socket_jh02.fd_array [I] = s)
{
If (socket_jh01.fd_count <fd_setsize)
{
Sockaddr_in CADD;
Int cadd_len = sizeof (CADD );
Socket snew = accept (S, (sockaddr *) & CADD, & cadd_len );
Fd_set (snew, & socket_jh01 );
Printf ("accept a client connection, peer address: [% s], Port: [% d] \ n", inet_ntoa (CADD. sin_addr), ntohs (CADD. sin_port ));
Printf ("sets of interfaces assigned to the client: % d \ n", snew );
}
Else
{
Printf ("too many connections \ n ");
Continue;
}
}
Else
{
Char cbuf [256];
Memset (cbuf, 0,256 );
Int crecv;
Crecv = Recv (socket_jh02.fd_array [I], cbuf, 256, 0 );
If (crecv = socket_error)
{
Printf ("the client % d may be disabled illegally !! ", Socket_jh02.fd_array [I]);
Printf ("or call Recv () failed, error = [% d] \ n", wsagetlasterror ());
Closesocket (socket_jh02.fd_array [I]);
Fd_clr (socket_jh02.fd_array [I], & socket_jh01 );
}
Else if (crecv> 0)
{
Printf ("received data to [% d]: % s \ n", socket_jh02.fd_array [I], cbuf );
Int isend;
Char sbuf [] = "Hello client! I am server ";
Isend = Send (socket_jh02.fd_array [I], sbuf, sizeof (sbuf), 0 );
If (isend = socket_error)
{
Printf ("Send () failed, error = [% d] \ n", wsagetlasterror ());
Break;
}
Else if (isend <= 0)
{
Printf ("message sending failed !! \ N ");
Break;
}
Else
Printf ("message sent to customer [% d], information length % d bytes \ n", socket_jh02.fd_array [I], isend );
}
Else
{
Printf ("client [% d] no longer sends data. Normally close the connection. The set of interfaces created for client connection will be closed !! \ N ", socket_jh02.fd_array [I]);
Closesocket (socket_jh02.fd_array [I]);
Fd_clr (socket_jh02.fd_array [I], & socket_jh01 );
}
}
} // End
} // End sock_sum
// ------------ Case 2 timeout
Else if (sock_sum = 0)
{
Printf ("number [% d] times out \ n", X );
If (x <3)
{
X ++;
Continue;
}
Else
{
Printf ("exceeds the waiting limit, exit program \ n ");
Break;
}
}
// -------------- Case 3 failed
Else
{
Printf ("select () failed, error = [% d] \ n", wsagetlasterror ());
Break;
}
} // While end
Closesocket (s );
Printf ("quit ");
Wsacleanup ();
Return 0;
}