Windows non-blocking or asynchronous sockets

Source: Internet
Author: User

Asynchronous vs. non-blocking differences see my other Article Socket synchronous/asynchronous vs. blocking/non-blocking differences

    1. Select

    2. WSAAsyncSelect

    3. WSAEventSelect

    4. Overlap (Overlapped) I/O

    5. IOCP: Completion port

Select

The first thing to do is to use ioctlsocket to set the non-blocking mode.

The thread is then started and a select is not kept in the thread.

WSAAsyncSelect

The WSAAsyncSelect model is the most easy-to-use socket I/O model under Windows. With this model, Windows notifies the application of network events in the context of the message. This model provides asynchronous notification of the ability to read and write data, but does not provide asynchronous data transfer. You need to send (typically resend) and receive in the message response function. Because the model is based on the Windows Messaging mechanism, windows must be created in the application . Although it is possible to determine whether the window is displayed in development.

WSAEventSelect

The

is typically used with wsacreateevent, Wsaresetevent, Wsacloseevent, wsawaitformultileevents, and wsaenumnetworkevents without creating a window. wsawaitformultileevents Check for an event, wsaenumnetworkevents enumeration event type, fd_read, fd_write and so on.

The function can support up to wsa_maximum_wait_events (64) objects. This function waits for a network event to occur, returns Wsa_wait_timeout if the specified time (dwtimeout) is over, and if an event occurs within the specified time, Returns the index of the event object (note: The actual index of the event to be expected in the program needs to be subtracted by the return value minus wsa_wait_event_0), and the call fails to return Wsa_wait_ FAILED. If you set the parameter fWaitAll to False if more than one network event occurs, the function returns only one Event object index, and the event is the first one in the array of event handles. The workaround is to loop through the function to process the following trusted events.

overlap (Overlapped) I/O

Unlike the previous model, the application that uses the overlapping model notifies the buffer transceiver system to use the data directly, that is, if the application posts a buffer of 10KB size to receive the data, and the data has reached the socket, the data is copied directly to the posted buffer. The previous model is in the socket buffer, when the notification application is received, after the data is copied to the program's buffer.

--Excerpt from http://zhoumf1214.blog.163.com/blog/static/5241940201211705318496/

In the case of receive, the previous model needed to copy itself from the socket buffer to the program buffer, while the overlapped IO was the operating system copying the data directly to the program buffer.

the core of an overlapping model is an overlapping data structure. If you want to use the file in overlapping ways, you must open it with the FILE_FLAG_OVERLAPPED flag.

There are 2 ways to achieve this:

1. Events

First waitforsingleobject/waitformultipleobjects or wsawaitformultipleevents the function, then call the (WSA) GetOverlappedResult () function, and finally, Using the pointer offset positioning allows you to accurately manipulate the data you receive.

Similar to other events, the maximum number is 64.

2. Completing the routine (not the completion port)

ReadFileEx (), passing the callback function pointer.

Completion Port

The so-called "completion port", which is actually an I/O construction mechanism used by WIN32, Windows NT, and Windows 2000, can actually accept something other than the socket handle (overlapping IO seems to be possible as well).

Before using this model, you first create an I/O completion Port object (createiocompletionport),

What is special about the Numberofconcurrentthread parameter is that it defines the number of threads that are allowed to execute on a completion port. Ideally, we want each processor to be responsible for running one thread, servicing the completion port, and avoiding too frequent thread "scene" switching. Setting this parameter to 0 indicates how many processors are installed in the system and how many threads are allowed to run concurrently!

1)   Create a completion port. The fourth parameter remains at 0, specifying that on the completion port, only one worker thread is allowed to execute at a time per processor.

2)   Determine how many processors are installed in the system.

3)   Create worker threads, based on step 2) to obtain the processor information, on the completion port, to service the completed I/O request. In this simple example, we create only one worker thread for each processor. This is due to the anticipation that there will not be any threads entering the "pending" state, resulting in a situation where the processor is idle due to a shortage of threads (there are not enough threads available to execute). When calling a C R e a T e t h r e A D function, you must also provide a worker routine that is executed by the thread at the time of creation. Thread responsibilities are discussed in detail later in this section.

4)   Prepare a listener socket to listen for incoming connection requests on Port 5 1 5 0.

5) use a C c e p T function to accept incoming connection requests.

6)   Create a data structure that holds the "single handle data" while depositing the accepted socket handle in the structure.

7)   Call C R e a T e I o c o m P l e t I o n P o r T, the new socket handle returned from a C c e p T is associated with the completion port. By completing the key (C o m P l e t i o n K e y) parameter, the data structure of the handler is passed to C R e a T e i o c o m P l e t i o n P o r T.

8)   START I/O operation on an accepted connection. Here, we want to post one or more asynchronous W s a R e C V or W s a s e n d requests through the overlapped I/O mechanism on the new socket. After these I/O requests are completed, a worker thread will service the I/O request while continuing to process future I/O requests and experience this later in the worker routines specified in step 3).

9)   Repeat steps 5) ~ 8) until the server is aborted.

 IOCP_TCPIP_Socket_Server.cpp#include <WinSock2.h> #include  <Windows.h> #include  <vector> #include  <iostream>using namespace std; #pragma  comment (Lib,   "Ws2_32.lib")// socket the dynamic link library #pragma comment (lib,  "Kernel32.lib") required for programming//  IOCP need to use the dynamic link library/** *  struct name:per_io_data *  structure function: Overlapped I/O required structure, temporary record IO data  **/const  int databuffsize  = 2 * 1024;typedef struct{overlapped overlapped; Wsabuf databuff;char buffer[ databuffsize ];int bufferlen;int operationtype;} per_io_operateion_data, *lpper_io_operation_data, *lpper_io_data, per_io_data;/** *  struct name:per_handle_data *  structure storage: Records the data of a single socket, including the socket variable and the corresponding client address of the socket.  *  structure function: When the server is connected to the client, the information is stored in the structure and the client's address is known to facilitate a return visit.  **/typedef struct{SOCKET socket; SOCKADDR_STORAGE&NBSP;CLIENTADDR;} per_handle_data, *lpper_handle_data;//  Define global Variables const int defaultport = 6000;vector < per_handle_data* >  clientgroup;//  records the client's vector group Handle hmutex = createmutex (null, false, null);D Word  winapi serverworkthread (Lpvoid completionportid);D Word winapi serversendthread ( Lpvoid ipparam);//  start main function int main () {//  load socket dynamic link library word wversionrequested =  makeword (2,&NBSP;2); //  Request 2.2 version of Winsock library wsadata wsadata;//  receive windows  Socket structure Information Dword err = wsastartup (wversionrequested, &wsadata);if  (0 !=  err) {//  Check the socket library for success cerr <<  "request windows socket library  error!\n "; System (" pause "); return -1;} if (Lobyte (wsadata.wversion)  != 2 | |  hibyte (wsadata.wversion)  != 2) {//  Check whether the required version of the socket font is requested WSACleanup ();cerr <<  " Request windows socket version 2.2 error!\n "; System (" pause "); return -1;}   Create IOCP Kernel object/** *  The prototype of the function that needs to be used:  * handle winapi createiocompletionport (      *    __in   HANDLE FileHandle,//  A file handle that has already been opened, or an empty handle, is typically a handle to the client      *    __in   handle  ExistingCompletionPort,//  IOCP handle already exists      *    __in    ULONG_PTR CompletionKey,//  completion key that contains the specified file for the specified I/O completion package      *     __in   DWORD NumberOfConcurrentThreads //  true concurrent simultaneous execution of the maximum number of threads, General referral is CPU core number *2     * ); **/handle completionport =  CreateIoCompletionPort ( invalid_handle_value, null, 0, 0);if  (NULL ==  Completionport) {//  Create IO Kernel object failed cerr <<  "Createiocompletionport failed. error:" &nbSp;<< getlasterror ()  << endl;system ("pause"); return -1;}   Create IOCP thread-thread pool//  determine the number of cores in the processor system_info mysysinfo; GetSystemInfo (&mysysinfo);//  processor-based core number create thread for (dword i = 0; i <  ( MYSYSINFO.DWNUMBEROFPROCESSORS&NBSP;*&NBSP;2);  ++i) {//  Create a server worker thread and pass the completion port to the thread handle  Threadhandle = createthread (null, 0, serverworkthread, completionport, 0,  NULL); if (null == threadhandle) {cerr <<  "create thread handle failed.  error: " << getlasterror ()  << endl;system (" pause "); return -1;} CloseHandle (Threadhandle);}   Set up flow socket Socket srvsocket = socket (af_inet, sock_stream, 0);//  Binds the socket to the native sockaddr_in srvaddr;srvaddr.sin_addr. S_un. S_addr = htonl (inaddr_any); srvaddr.sin_family = af_inet;srvaddr.sin_port = htons (defaultport); int bindresult = bind (srvsocket,  (sockaddr*) &srvaddr, sizeof (SOCKADDR)); if (SOCKET_ Error == bindresult) {cerr <<  "Bind failed. error:"  <<  GetLastError ()  << endl;system ("pause"); return -1;}   Set the SOCKET to listen mode Int listenresult = listen (SRVSOCKET,&NBSP;10); if (socket_error ==  listenresult) {cerr <<  "listen failed. error: "  <<  GetLastError ()  << endl;system ("pause"); return -1;}   started processing IO data cout <<  "This server is ready to wait for client access ... \ n";//  create a thread to send the data handle sendthread  = createthread (Null, 0, serversendthread, 0, 0, null); while (true) {PER_ handle_data * perhandledata = null; sockaddr_in saremote;int remotelen; socket acceptsocket;//  receive the connection and assign the completion end, here can be used AcceptEx () remotelen = sizeof (saremote); Acceptsocket =&nBsp;accept (srvsocket,  (sockaddr*) &saremote, &remotelen); if (socket_error ==  AcceptSocket) {//  receive client failed cerr <<  "accept socket error: "  <<  getlasterror ()  << endl;system ("pause"); return -1;}   Create a handle data structure perhandledata =  (lpper_handle_data) GlobalAlloc (gptr, sizeof (per_) used to associate with sockets Handle_data));//  the memory for this perhandledata in the heap for the specified size perhandledata -> socket =  acceptsocket;memcpy  (&perhandledata -> clientaddr, &saremote, remotelen); Clientgroup.push_back (Perhandledata);//  Place a single client data pointer in the client group//  will accept the socket and completion Port Association CreateIoCompletionPort (( HANDLE) (Perhandledata -> socket), completionport,  (DWORD) perhandledata, 0);//   Starts processing I/O on the accept socket using overlapped I/O mechanism//  post one or more asynchronous//&NBSP;WSARECV or WSASend requests on a new socket, and after these I/O requests are completed, the worker thread will service the I/O request//   Single I/O operation data (I/O overlap) lpper_io_operation_data periodata = null; Periodata =  (Lpper_io_operation_data) GlobalAlloc (gptr, sizeof (per_io_operateion_data)); ZeroMemory (& (periodata -> overlapped),  sizeof (overlapped)); periodata->databuff.len = 1024; periodata->databuff.buf = periodata->buffer; periodata->operationtype = 0;// readdword recvbytes;dword flags = 0; WSARecv (perhandledata->socket, & (Periodata->databuff), 1, &recvbytes, & flags, & (periodata->overlapped),  null);} System ("pause"); return 0;}   Start service worker thread function Dword winapi serverworkthread (lpvoid ipparam) {Handle completionport  =  (HANDLE) ipparam;dword bytestransferred; lpoverlapped ipoverlapped; lpper_handle_data perhandledata = null; lpper_io_data periodata = null;dword recvbytes;dword flags = 0; Bool bret = false;while (true) {Bret = getquEuedcompletionstatus (completionport, &bytestransferred,  (pulong_ptr) &PerHandleData,  ( lpoverlapped*) &ipoverlapped, infinite); if (bret == 0) {cerr <<  " getqueuedcompletionstatus error:  " << getlasterror ()  << endl;return  -1;} periodata =  (Lpper_io_data) Containing_record (ipoverlapped, per_io_data, overlapped);//   Check if an error occurs on the socket if (0 == bytestransferred) {closesocket (perhandledata->socket); GlobalFree (Perhandledata); GlobalFree (periodata); continue;}   begins data processing and receives WaitForSingleObject from the client (hmutex,infinite);cout <<  "A client says :  " << PerIoData->databuff.buf << endl; ReleaseMutex (Hmutex);//  establishes single I/O operation data for the next overlapping call ZeroMemory (& (periodata->overlapped),  sizeof ( OVERLAPPED)); //  empty memory periodata->databuff.len = 1024; Periodata->databuff.buf = periodata-&gT;buffer; Periodata->operationtype = 0;// readwsarecv (perhandledata->socket, & (PerIoData- >databuff), 1, &recvbytes, &flags, & (periodata->overlapped),  NULL);} return 0;}   Thread execution function for sending information Dword winapi serversendthread (Lpvoid ipparam) {while (1) {char talk[200]; Gets (talk);int len;for  (len = 0; talk[len] !=  ';  ++len) {//  Find out the length of this character set}talk[len] =  ' \ n ';talk[++len] =  ';p rintf ("I say:");cout <<  talk; WaitForSingleObject (Hmutex,infinite); for (Int i = 0; i < clientgroup.size ();  ++i) {Send (clientgroup[i]->socket, talk, 200, 0);//  sends the message}releasemutex (HMutex);  }return 0;}



Windows non-blocking or asynchronous sockets

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.