WinSock WSAEventSelect Model

Source: Internet
Author: User

In front of us, we talked about the WSAAsyncSelect model, which provides a mechanism compared to the Select model: when the corresponding IO notification occurs, the operating system is notified immediately, and the corresponding handler function is called, which solves the timing problem of calling send and recv. But it has one obvious drawback, that it has to rely on Windows. Another model is provided for this Winsock WSAEventSelect

Introduction to the Model

The main feature of the model is that it uses event handlers to complete notification of socket events. Similar to the WSAAsyncSelect model, it also allows you to use event objects to complete notifications for multiple sockets.
The model first calls Wsacreateevent on each socket handle to create a Wsaevent object handle (the earlier wsaevent differs from the traditional event handle, but it is the same thing from the WinSock2.0). Then call WSAEventSelect to bind the socket handle to the Wsaevent object, and eventually wsawaitformultievents to wait for the wsaevent to become signaled before processing the corresponding socket.

Wsaevent has two modes of operation and working status
The working state has the signal and no signal two kinds
The working mode has manual reset and manual reset, and manual reset means that Wsaevent does not automatically change to no signal when wsawaitformultievents or wsawaitforsingleevents returns. You need to call wsaresetevent manually to set the Wsaevent object to no signal, and an automatic reset means that each time the wait function returns, it is automatically reset to no signal, and the Wsaevent object created by the call wsacreateevent needs to be reset manually. If you want to create an Wsaevent object that is automatically reset, you can call the CreateEvent function to create it (because there is no difference between the two after WinSock2.0, you only need to call CreateEvent and convert the return value to Wsaevent)

The WSAEventSelect function is prototyped as follows:

int WSAEventSelect(  SOCKET s,  WSAEVENT hEventObject,  long lNetworkEvents);

where s means that the corresponding socket,heventobject represents the corresponding Wsaevent object, lnetworkevents indicates which events we need to handle, and it has some corresponding macro definitions

Network Events the corresponding meaning
Fd_read Data receive operations are currently available, and functions such as recv, Recvfrom, WSARecv, or wsarecvfrom can be called at this time
Fd_write You can send data at this time, you can call send, SendTo, WSASend, or WSASendTo
Fd_accept You can call accept (Windows Sockets) or wsaaccept unless the error code returned is Wsatry_again.
Fd_connect Indicates that a remote server can currently be connected
Fd_close Currently receiving a shutdown message

When WSAWaitForMultipleEvents returns, it also returns an ordinal that identifies which wsaevent in the array has a signal, and we use it to get the subscript for the index - WSA_WAIT_EVENT_0 corresponding wsaevent in the array. Then the corresponding socket can be found based on the event object.
After obtaining the corresponding socket, we also need to obtain the current event which causes it to become signaled, we can call the Wsaenumnetworkevents function to get the corresponding network event.

int WSAEnumNetworkEvents(    SOCKET s,    WSAEVENT hEventObject,    LPWSANETWORKEVENTS lpNetworkEvents);

S is the socket handle to get its specific event notification
Heventobject is the corresponding wsaevent handle, can not be passed in, because the socket handle has been explained to get the notification on that handle, of course, if passed in, then this function will do a reset to this wsaevent, set as no signal state, Equivalent to a wsaresetevent call. At this point, we don't need to call the Wsaresetevent function.

The last parameter is a struct, and the structure is defined as follows:

typedef struct _WSANETWORKEVENTS {      long lNetworkEvents;      int iErrorCode[FD_MAX_EVENTS];} WSANETWORKEVENTS,  *LPWSANETWORKEVENTS;

The first data is a network event that is currently generated.
The Ierrorcode array is the error code that corresponds to each network event, for each event error code its specific array subscript is a predefined set of Fd_ that begins with a string followed by a _bit ending macro, such as Fd_read event corresponding error code subscript is Fd_read_bit

The following code shows an example code that handles event errors that receive (read) data

if (NetworkEvents.lNetworkEvents & FD_READ){    if0)    {       printf("FD_READ failed with error %d\n",           NetworkEvents.iErrorCode[FD_READ_BIT]);    }}

So far, we can summarize the steps to use the WSAEventSelect model

    1. Call Wsacreateevent to create a wait object for each socket and map it to the corresponding socket
    2. Call the WSAEventSelect function to bind the socket to the Wsaevent object
    3. Call the WSAWaitForMultipleEvents function to wait for all socket handles
    4. When the WSAWaitForMultipleEvents function returns, the corresponding Wsaevent object and the socket object are found using the returned index
    5. Call wsaenumnetworkevents to get the corresponding network events, according to network events to do the corresponding send and receive operations
    6. Steps to repeat
Example

Here's a simple example.

int  _tmain (    int  argc, TCHAR *argv[]) {wsadata WD = {0 };    WSAStartup (Makeword (2 , 2 ), &WD);    Socket skserver = socket (af_inet, sock_stream, IPPROTO_IP);    Sockaddr_in addrserver = {af_inet};    Addrserver.sin_port = htons (Server_port);    ADDRSERVER.SIN_ADDR.S_ADDR = htonl (Inaddr_any);    Bind (Skserver, (sockaddr*) &addrserver, sizeof  (sockaddr));    Listen (Skserver, 5 ); printf (" service is listening .....  \n     );    Cwsaevent wsaevent; Wsaevent.insertclient (Skserver, fd_accept |    Fd_close);    Wsaevent.eventloop ();    WSACleanup (); return  0 ;}  

A class cwsaevent is defined in the code that encapsulates the operations associated with the model and the corresponding event object and socket object, first creating a listening socket in the main function, then binding, listening, and submitting the listener socket to the class to manage it. The function insertclient is defined as follows:

voidlong lNetworkEvents){    m_socketArray[m_nTotalItem] = skClient;    m_EventArray[m_nTotalItem] = WSACreateEvent();    WSAEventSelect(skClient, m_EventArray[m_nTotalItem++], lNetworkEvents);}

This function adds the corresponding member to the corresponding location of the event array and the socket array, and then calls WSAEventSelect.

The EventLoop function of the class defines a loop to repeat the preceding steps, and some of the code for the function is as follows:

intCwsaevent::waitforallclient () {DWORD dwret = wsawaitformultipleevents (M_ntotalitem, M_eventarray, FALSE, WSA_INFINITE    , FALSE); Wsaresetevent (M_eventarray[dwret-wsa_wait_event_0]);returnDwret-wsa_wait_event_0;}intCwsaevent::eventloop () {wsanetworkevents Wne = {0}; while(TRUE) {intNret = Waitforallclient (); Wsaenumnetworkevents (M_socketarray[nret], M_eventarray[nret], &wne);if(Wne.lnetworkevents & Fd_accept) {if(0! = Wne.ierrorcode[fd_accept_bit]) {onaccepterror (Nret, M_socketarray[nret], wne.ierrorcode[fd_a            Ccept_bit]); }Else{onacccept (nret, M_socketarray[nret]); }        }Else if(Wne.lnetworkevents & Fd_close) {if(0! = Wne.ierrorcode[fd_close_bit]) {oncloseerror (Nret, M_socketarray[nret], Wne.ierrorcode[fd_clo            Se_bit]); }Else{OnClose (nret, M_socketarray[nret]); }        }Else if(Wne.lnetworkevents & Fd_read) {if(0! = Wne.ierrorcode[fd_read_bit]) {onreaderror (Nret, M_socketarray[nret], Wne.ierrorcode[fd_read_            BIT]); }Else{OnRead (nret, M_socketarray[nret]); }        }Else if(Wne.lnetworkevents & Fd_write) {if(0! = Wne.ierrorcode[fd_write_bit]) {onwriteerror (Nret, M_socketarray[nret], Wne.ierrorcode[fd_wri            Te_bit]); }Else{Onwrite (nret, M_socketarray[nret]); }        }    }}

The function first waits, when the wait function returns, obtains the corresponding subscript, obtains to the socket and the event object, then calls the wsaenumnetworkevents to obtain the corresponding network event, finally according to the event calls the different processing function to handle
In the above code, this loop has a potential problem, we envision a scenario where there are multiple clients connecting to the server at the same time, the first time we wait to return, we focus on the processing of the IO event, that is, responding to this client A's request, when client A sends a request, And a few other client B then also sent a request, after the first processing is completed, wait for the client A, and the subsequent client B's request is queued up, if the client A has been sending requests continuously, the problem is that the server has been responding to a request, and for B, Its request was slow to respond. To avoid this problem, we can set the number of waits to 1 for each socket loop in the array after the function wsawaitformultipleevents returns, and set the timeout value to 0, At this point, the function is equivalent to looking at each socket in the array to see if it is pending, when all the traversal is complete, processing the requests in turn, or specifically creating the corresponding thread to handle the request.

Finally, the entire sample code

WinSock WSAEventSelect Model

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.