Winsock provides another useful asynchronous event notification I/O model-wsaeventselect model. Similar to the wsaasyncselect model, this 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-driven mechanism of windows, but is notified through the event object handle. The following example shows how to implement the same function as the previous two articles (one & Two & Three): the client connects to the server and sends data to the server. The server receives and outputs the data sent from the client. The server still processes multi-client connections in a single thread.
Server. cpp -----------------------------
# Include <iostream> # include <winsock2.h> # include <windows. h> using namespace STD; # pragma comment (Lib, "ws2_32.lib ") # define port_no 6000 # define backlog 10 // record the socket and corresponding event array and array size wsaeventeventarray [wsa_maximum_wait_events] = {0}; socketsockarray [events] = {0 }; int neventtotal = 0; // empty array element with the serial number nindex: socket and eventvoid clearindex (INT nindex); int main (INT argc, char * argv []) {wsadata WSA Data; int ret; Word wversionrequested = makeword (2, 2); socket socksrv; sockaddr_in addrsrv; // initialize Windows Socket ------ ret = wsastartup (wversionrequested, & wsadata ); if (Ret! = 0) {cout <"wsastartup () failed:" <wsagetlasterror () <Endl; Return-1 ;}// create socket ------ socksrv = socket (af_inet, sock_stream, 0); If (invalid_socket = socksrv) {cout <"socket () failed:" <wsagetlasterror () <Endl; wsacleanup (); return-1;} addrsrv. sin_addr.s_un.s_addr = htonl (inaddr_any); addrsrv. sin_family = af_inet; addrsrv. sin_port = htons (port_no); // bind socket ------ ret = BIND (socksrv, (S Ockaddr *) & addrsrv, sizeof (sockaddr); If (socket_error = RET) {cout <"BIND () failed:" <wsagetlasterror () <Endl; closesocket (socksrv); wsacleanup (); Return-1;} // listen ------ ret = listen (socksrv, backlog); If (socket_error = RET) {cout <"Listen () failed:" <wsagetlasterror () <Endl; closesocket (socksrv); wsacleanup (); Return-1 ;} cout <"server started ...... "<Endl; // create the wsaevent corresponding to socksrv and add it to the array ---- -- Wsaevent wsaevt = require (); wsaeventselect (socksrv, wsaevt, fd_accept | fd_close); eventarray [neventtotal] = wsaevt; sockarray [neventtotal] = socksrv; neventtotal ++; // socket Event Response ------ while (1) {int nindex = wsawaitformultipleevents (neventtotal, eventarray, false, wsa_infinite, false); If (wsa_wait_failed = nindex) {cout <"wsawaitformultipleevents failed:" <wsagetlasterror () <Endl; break;} Nindex = nindex-events; socket sock = sockarray [nindex]; wsaevent wsaevt = eventarray [nindex]; wsanetworkevents networkevts; dependencies (sock, wsaevt, & networkevts); If (networkevts. lnetworkevents & fd_accept) // --- fd_accept {If (networkevts. ierrorcode [fd_accept_bit] = 0) {sockaddr_in addrclient; int Len = sizeof (sockaddr); socket sockconn = accept (sock, (sockaddr *) & addrclient, & Len ); If (invalid_socket = sockconn) {cout <"accept () failed:" <wsagetlasterror () <Endl; continue;} cout <"receives a new connection: "<inet_ntoa (addrclient. sin_addr) <Endl; If (neventtotal> = wsa_maximum_wait_events) {cout <"too has connections! "<Endl; closesocket (sockconn); continue;} wsaevent sockconnevt = require (); wsaeventselect (sockconn, sockconnevt, fd_read | fd_close | fd_write); eventarray [neventtotal] = sockconnevt VT; sockarray [neventtotal] = sockconn; neventtotal ++ ;}} else if (networkevts. lnetworkevents & fd_read) // --- fd_read {If (networkevts. ierrorcode [fd_read_bit] = 0) {char recvbuffer [max_path] = {0}; int ret = Recv (sock, recvbuffer, sizeof (recvbuffer), 0 ); if (ret = 0) {cout <"connection has been gracefully closed. "<Endl; closesocket (sock); closehandle (wsaevt); clearindex (nindex); continue;} else if (ret = socket_error) {cout <"connection has been closed ungracefully. "<Endl; closesocket (sock); closehandle (wsaevt); clearindex (nindex); continue;} cout <" receive data from client: "<recvbuffer <Endl ;}} else if (networkevts. lnetworkevents & fd_close) // --- fd_close {If (networkevts. ierrorcode [fd_close_bit] = 0) {cout <"connection has been gracefully closed. "<Endl;} else {cout <" connection has been closed ungracefully. "<Endl;} closesocket (sock); closehandle (wsaevt); clearindex (nindex);} else if (networkevts. lnetworkevents & fd_write) // --- fd_write {}} // clear the resource ------ for (INT I = 0; I <neventtotal; ++ I) {closesocket (sockarray [I]); closehandle (eventarray [I]);} wsacleanup (); cout <"exit... "<Endl; return 0;} // empty array elements with the serial number nindex: socket and eventvoid clearindex (INT nindex) {// parameter validity check 0 = <nindex <= WSA_MAXIMUM_WAIT_EVENTS-1if (nindex <0 | nindex> = wsa_maximum_wait_events | nindex> = neventtotal) return; // clear the last element, 0 if (nindex = neventtotal-1) {eventarray [nindex] = 0; sockarray [nindex] = 0; neventtotal --; return ;} // forward (INT I = nindex; I <= nEventTotal-2; ++ I) {eventarray [I] = eventarray [I + 1]; sockarray [I] = sockarray [I + 1]; neventtotal --;}}
Client. cpp -----------------------------
# Include <iostream> # include <windows. h> using namespace STD; # pragma comment (Lib, "ws2_32.lib") # define port_no 6000 # define srv_ip_addr "127.0.0.1" int main (INT argc, char * argv []) {int ret; wsadata; Word wversionrequested = makeword (2, 2); socket sockclient; sockaddr_in addrsrv; // initialize Windows Socket ------ ret = wsastartup (wversionrequested, & wsadata ); if (Ret! = 0) {cout <"wsastartup () failed:" <wsagetlasterror () <Endl; Return-1 ;}// create socket ------ sockclient = socket (af_inet, sock_stream, 0); If (invalid_socket = sockclient) {cout <"socket () failed:" <wsagetlasterror () <Endl; wsacleanup (); return-1;} addrsrv. sin_addr.s_un.s_addr = inet_addr (srv_ip_addr); addrsrv. sin_family = af_inet; addrsrv. sin_port = htons (port_no); // connection ------ ret = connect (sockclient, (sockaddr *) & addrsrv, sizeof (sockaddr); If (socket_error = RET) {cout <"Connect () failed:" <wsagetlasterror () <Endl; closesocket (sockclient); wsacleanup (); Return-1 ;} else {cout <"Connect () successfully. "<Endl;} // send data ------ char sendbuf [max_path] = {0}; while (1) {cin. getline (sendbuf, sizeof (sendbuf); If (strcmp (sendbuf, "exit") = 0) {break;} ret = Send (sockclient, sendbuf, strlen (sendbuf) + 1, 0); If (socket_error = RET) {cout <"Send () failed:" <wsagetlasterror () <Endl; closesocket (sockclient ); wsacleanup (); Return-1 ;}// clear resources ------- closesocket (sockclient); wsacleanup (); cout <"exit... "<Endl; return 0 ;}