Winsock provides some I/O models to help applications manage I/O asynchronously on one or more socket words.
There are about 6 types: Blocking model, select model, wsaasyncselect model, wsaevenetselect model, overlap model, and complete port model.
Blocking Mode:
When a socket word is created, it works in blocking mode by default. When the Recv fails to receive the message, it will wait until it is blocked. Advantage: it is easy to use and suitable for learning. Disadvantage: multiple threads are required when multiple sockets are connected, which is rarely used in actual development.
Non-blocking mode:
U_long ul = 1; socket S = socket (af_inet, sock_stream, 0); ioctlsocket (S, fionbio, (u_long *) & UL); // three lines of code, set to non-blocking mode.
After the non-blocking mode is set, the Winsock call that processes sending and receiving aura or management connection will return immediately. In most cases, the error code is wsaewouldblock, indicating that the request operation was not completed during the call.
This requires multiple calls to obtain the desired results. It will affect the program performance. It is rarely used in actual development.
Select model:
The select model is widely used in WinSock and uses the select function to manage I/O.
The select function can determine the status of one or more sockets. If there is no network time, wait for the status.
Int select (INT NFDs, // ignore fd_set * readfds, // point to a socket set to check readability fd_set * writefds, // point to a socket set, used to check the writability fd_set * writable TFDs, // points to a socket set, used to check the const struct timeval * timeout // used to specify the waiting time. If it is null, It is infinitely large );
If the function is successfully called, the total number of sockets is returned. If the wait time is reached, 0 is returned. If the call fails, socket_error is returned.
The fd_set structure connects multiple sockets to form a socket set.
Macro of four fd_set socket sets: fd_zero (* Set) is initialized to an empty set, fd_clr (S, * Set) is removed from the set socket S, fd_isset (S, * Set) check whether s is a set member. If yes, return true, fd_set (S, * Set) to add socket to the set.
To test whether s is readable, add it to the set first and wait for the select function to return. After the SELECT statement is executed, judge whether s is still in the set. If yes, it indicates that S is readable.
Specific programming process:
(1) initialize the socket set fssocket and add a listening socket handle to the set.
(2) Pass the copy fdread of the fdsocket set to the select function. when an event occurs, the select function removes the socket handle that has no pending I/O operations in the fdread set. (For my understanding of this, I think so, the select function will only retain the socket handle in the set that requires I/O operations), and then return.
(3) Compare the fdread set processed by the fdsocket set and select, determine which sockets have pending I/O (which sockets have I/O messages), and process these I/O messages.
The benefit of using select is that the program can simultaneously process multiple socket connections in a single thread, avoiding the thread expansion problem in blocking mode. However, the socket data in the fd_set structure is limited. The maximum value is fd_setsize, Which is 64 in winsock2.h. Of course, this can be modified, but the maximum value is only 1024. In addition, if fd_setsize is too large, the server needs to check too many sockets, which may affect the performance.
Wsaasyncselect Model
The wsaasyncselect model allows applications to receive network event notifications in the form of Windows messages. This model is set to apply to the Windows message driver environment. Currently, many network applications with low performance requirements use the wsaasyncselect model, and the csocket class in MFC also uses it.
The wsaasyncselect function automatically sets the socket to non-blocking mode and binds a window handle to the socket. When a network event occurs, a message is sent to the window.
Int wsaasyncselect (socket S, // The socket handle hwnd to be set, // specify a window handle. When the socket notification message is sent to the corresponding window, u_int wmsg, // long Levent Message ID received when a network event arrives // specify the notification codes to be sent); // The last parameter Levent specifies the notification code to be sent, it can be a combination of the following values: fd_read // The socket receives the packet sent by the other party, indicating that it can read the socket fd_write // when the buffer is full and then empty again, the Winsock interface uses this notification code to notify the application. It indicates that the socket in the fd_accept // listener can continue to send data and detects a connection to the fd_connect // use a socket to connect to the host of the other party, after the connection is completed, the notification code fd_close // detects that the socket connection is closed.
The most prominent feature of the wsaasyncselect model is that it is integrated with the message driver mechanism of windows, which makes it easy to develop network programs with GUI interfaces. However, if the number of connections increases, the server performance will inevitably be affected when a single windows function processes thousands of client requests.
Wsaeventselect Model
Similar to the wsaeventselect model, the wsaasyncselect model allows applications to receive event-based network notifications on one or more sockets. It is similar to the wsaasyncselect model because it also receives network events of the fd_xxx type. However, it does not rely on the message mechanism of windows, but is notified through the event object handle.
The basic idea is to create an event object for a group of network events of interest, and then call the wsaeventselect function to attach network events and event objects. When a network event occurs, Winsock makes the corresponding event object trusted, and the wait function on the event object will return. Then, call the wsaenumnetworkevents function to obtain the network events.
Wsaevent wsacreateevent (void); // return a manually reset event object handle int wsaeventselect (socket S, // socket handle wsaevent heventobject, // event object handle long lnetworkevents // a combination of fd_xxx network events of interest); // after a network event is associated with an event object, the application can wait on the event object. Winsock provides the following function DWORD wsawaitformultipleevents (DWORD cevents, // specify the number of event object handles in the array referred to by lphevents below. Const wsaevent * lphevents, // specify an event object handle array bool fwaitall, // specify whether to wait for all event objects to change to the trusted DWORD dwtimeout, // specify the waiting time, wsa_infinite is an infinite bool falertable // you can ignore it when using the wsaeventselect model. It should be set to false );
The wsaeventselect model is easy to use and does not require a window environment. However, the disadvantage is that
Wsawaitformultipleevents supports up to 64 objects. To manage more objects, you need to create a thread.