Windows completion port IOCP Model (ii)

Source: Internet
Author: User

1 Detailed completion port basic use

1 Creating the completion port

HANDLE IOCP = CreateIoCompletionPort (invalid_handle_value,null,0,0);

The parameter is actually -1,0,0,0. The last parameter represents the

NumberOfConcurrentThreads, which is the number of threads that allow the app to execute concurrently,

The future avoids context switching, which means that only one thread per CPU is allowed, set to 0

Is how many processors there are, and how many are working threads.

The reason is if a machine has two CPUs (two cores), if you let the system run simultaneously

Thread, more than the number of native CPUs, it makes no sense to waste CPU precious cycles,

Reduce efficiency, not worth the candle.

A handle is then returned as long as it is not null and the completion port is established successfully.



2 Create socket bindings listen, not much.

socket lo_sock = invalid_socket;//creation failed if  (iocp == null) {goto failed;} Create a thread    IOCP into the thread function H_threads = createthread (null, 0, serverthread,  ( LPVOID) iocp, 0, 0);//  Prevent memory leaks closehandle (h_threads);//end//Create Socketlo_sock = socket (AF _inet,sock_stream,0);if  (lo_sock == invalid_socket) {goto failed;} Struct sockaddr_in addr;memset (&addr, 0, sizeof (addr)); addr.sin_addr.s_addr =  INET_ADDR ("127.0.0.1"); Addr.sin_port = htons (port); addr.sin_family = af_inet;int  ret = bind (lo_sock,  (const struct sockaddr*) &addr, sizeof (addr));   (ret != 0) {printf ("bind %s:%d error \n",  "127.0.0.1",  port); goto  failed;} printf ("bind %s:%d success \n",  "127.0.0.1",  port);p rintf ("Starting listener  on %d\n ",  port);// SOMAXCONN  Specify the maximum queue length by listen Ret = listen (lo_sock, somaxconn);if  (ret != 0) {printf (" Listening on port failed\n "); goto failed;} printf ("listening on success\n");




3 listen for accept in main thread

struct sockaddr_in c_addr;int len = sizeof (c_ Addr)///No client access, thread hangs    blocking int client_fd = accept (lo_sock,  (struct  sockaddr*) &c_addr, &len);if  (client_fd != invalid_socket) {         //here is a new socket connected to   printf ("new client %s:%d coming\n",  Inet_ntoa (C_ADDR.SIN_ADDR),  ntohs (C_addr.sin_port));     }    else {continue;} Save session Information   struct session* s = save_session (Client_fd, inet_ntoa (c_addr.sin_ Addr),  ntohs (C_addr.sin_port)); Save the information in a structure that stores the user's ip port   port    The structure is like this:/*  This structure defines the STRUCT  SESSION{CHAR C_IP[32]; //IP address int c_port;  //Port int c_ Sock;  //socket handle int removed;//Delete tag struct  session * _next; //linked list pointer};*/ 



4 then bind the acquired client socket to the IOCP

This code is performed in a while (1) dead loop

Let's introduce this function and create a completion port with an API

Handle winapi createiocompletionport (__in  handle filehandle,  // This is where the customer is connected socket__in_opt handle existingcompletionport,//is the completion port created earlier,__in ulong_prt  completionkey,//This parameter can be passed a struct, a custom structure body                                  //you just pass the structure in, the worker thread can take it out,                                //   I'm using the   structure I defined above                                _in   dword dword numberofconcurrenthreads//said above, set to 0 on the line);//Add to this completion port CreateIoCompletionPort ((HANDLE) CLIENT_FD, IOCP, (DWORD) s, 0The;client_fd  is the client socket above or IOCP the completion port, and   s is the struct with the client session information 


5 posting an asynchronous RECV request

(That is, tell the completion port if I have this client have the package over, you want to receive the completion, then tell me)

Before you do this, define a struct as a sign, because when you start, you deliver a lot of

I/O requests, to bind each I/O operation with a flag so that after the network operation is complete,

The data returned by this group are found in this flag:

Be sure to put wsaoverlapped first, other casual


Buffer size # max_recv_size 8092struct io_package{wsaoverlapped overlapped;                    Overlapped I/O network operation is to use this overlapping structure int opt;               The type of the token request int pkg_size;           The length of the package wsabuf Wsabuffer;   A buffer that stores data that is used to pass data to overlapping operations char Pkg[max_recv_size]; The buffer};//listener event corresponding to the WSABUF is used to mark the type of request Enum{iocp_accept = 0,iocp_recv,iocp_write,};

WSARecv function

int WSARecv (socket s,//is of course the socket for this operation Lpwsabuf Lpbuffers,//Receive buffer DWORD Dwbuffercount,//Array WSABUF structure Number, set to 1 Lpdword LPNUMBEROFBYTESRECVD,//If the receive operation is completed immediately, this returns the number of bytes received by the function call Lpdword lpflags,//set to 0 Lpwsaoverl apped lpoverlapped,//This socket corresponds to the overlapping structure lpCompletionRoutine//This parameter only the completion of the routine mode will be used,) Wsa_io_pending: The most common return value, stating that the WSA Recv succeeded, but I/O operation was not completed

Post this request

struct io_package* io_data = malloc (sizeof (struct io_package))//only need to be emptied once, so that the overlapping structure can be emptied memset (io_data, 0, sizeof ( struct io_package)); io_data->wsabuffer.buf = Io_data->pkg;io_data->wsabuffer.len = Max_recv_size-1;io_ data->opt = IOCP_RECV; Mark request type we set to receive DWORD DwFlags = 0;//..... WSARecv (CLIENT_FD, &io_data->wsabuffer, 1, Null,&dwflags, &io_data->overlapped, NULL);


5 Waiting for the completion event in the worker thread

GetQueuedCompletionStatus function prototype, is the work thread to

Using the API, once he enters, the worker thread will be suspended, knowing

The completed event appears on the completion port. or network timeout

Then this thread will be awakened immediately, executing subsequent code

BOOL WINAPI getqueuedcompletionstatus (__in HANDLE completionport,//This is the only completion port we've built. __out Lpdword Lpnumberofbytes,//This is the number of bytes returned after the operation is completed __out pulong_ptr lpCompletionKey,//This is the custom struct parameter that is bound when the port is set to complete __out Lpoverl apped *lpoverlapped,//This is the overlapping structure that is established together when the socket is connected __in DWORD dwmilliseconds//waits for the completion port timeout, Wsa_inf Inite is to wait for an event before returning


Take a look at this code operation

Thread function Static dword winapi serverthread (lpvoid lparam) {//Get completion port handle iocp =   (HANDLE) lparam;//the number of bytes returned dword dwtrans;//the struct with the socket handle   because it was previously added   This function can be removed struct  session* s;//structure with overlapping structure struct io_package* io_data;//wait for iocpwhile  (1) {     s = null;dwtrans = 0;io_data = null;//calls this api  wait event int ret =  getqueuedcompletionstatus (iocp, &dwtrans,  (Lpdword) &s,  (lpoverlapped*) &io_ Data, wsa_infinite);if  (ret == 0) {printf ("iocp error");//IOCP port error continue;} To tell all users that the socket completion event occurred with printf ("iocp have event\n");//Bytes received ==0  indicate client disconnects if  (dwtrans ==  0) {//socket closed         closesocket (s->c_sock);         //Release Memory free (io_data);  continue;} Here means the data as well as read to//Here is the event type switch  (io_data->opt) {case iocp_recv:{ //  received the data and completed the io_data->pkg[dwtrans] = 0;printf ("iocp %d: recv %d,%s\n ", s->c_port,dwtrans,io_data->pkg);//When a read request is completed,  must post a read request again dword dwflags = 0;int  RET = WSARECV (S->c_sock, &io_data->wsabuffer, 1, null, &dwflags,  &io_data->overlapped, null);} Break;case iocp_write:{}break;case iocp_accept:{}break;default:break;}} return 0;}

In fact, we have finished the use of this IOCP, which will be added later.







Windows completion port IOCP Model (ii)

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.