Complete the port iocp Programming Model

Source: Internet
Author: User

Introduction

The basic idea of port completion is very similar to the DMA in the computer composition principle. The customer calls the overlap operation to throw a read/write request and waits for the completion of the port in the worker thread, the customer performs subsequent read/write operations based on the returned values. After the user throws an asynchronous read/write request, you can do other things.

1. define the structure of data stored in asynchronous requests

Enum io_operation {io_read = 1, io_send = 2, io_accept = 3,}; struct io_data {wsaoverlapped overlapped; // atomic lock DWORD dwlock; // time when data was last received, determine the inactive connection time DWORD dwentertick; // operation code io_operation opcode; // network socket handle socket activesocket; // network address DWORD dwipaddr; // port word wport; // request type char creqtype; // proxy_http; proxy_none; // buffer wsabuf; // Number of Io bytes processed DWORD dwrecved; // total number of buffer bytes DWORD dwrecvbuftail; // The buffer char recvbuffer [max_buff_size] directed by wsabuf; // Number of Io bytes processed DWORD dwsent; // The total number of buffer bytes DWORD dwsendbuftail; // The buffer char sendbuffer [max_buff_size] pointed by wsabuf;};

2. initialize listen

Void listenthread (void * ARGs) {// init Winsock2 wsadata; zeromemory (& wsadata, sizeof (wsadata); int retval =-1; if (retval = wsastartup (makeword (2, 2), & wsadata ))! = 0) {putlog ("wsastartup failed: Reason code: % u \ n", retval); Return ;}{// init TLS index if (! Inittlsindex () return ;}{// create socket g_serversocket = wsasocket (af_inet, sock_stream, ipproto_tcp, null, 0, wsa_flag_overlapped); If (g_serversocket = invalid_socket) {putlog ("server socket creation failed: Reason code: % u \ n", wsagetlasterror (); Return ;}{// bind sockaddr_in service; service. sin_family = af_inet; service. sin_addr.s_addr = htonl (inaddr_any); service. sin_port = Hton S (phone_port); int retval = BIND (g_serversocket, (sockaddr *) & service, sizeof (Service); If (retval = socket_error) {putlog ("server soket bind failed: Reason code: % u \ n", wsagetlasterror (); Return ;}{// listen int retval = listen (g_serversocket, 100); If (retval = socket_error) {putlog ("server socket listen failed: Reason code: % u \ n", wsagetlasterror (); return ;} putlog ("server socket Listen at: % d \ n ", phone_port) ;}{// create iocp system_info sysinfo; zeromemory (& sysinfo, sizeof (system_info); getsysteminfo (& sysinfo ); g_threadcount = sysinfo. dwnumberofprocessors + 1; g_hiocp = createiocompletionport (invalid_handle_value, null, 0, g_threadcount); If (g_hiocp = NULL) {putlog ("createiocompletionport () failed: reason :: % u \ n ", getlasterror (); return;} If (createiocompletionp ORT (handle) g_serversocket, g_hiocp, 0, 0) = NULL) {putlog ("binding server socket to Io completion port failed: Reason code: % u \ n ", getlasterror (); Return ;}{// create worker threads for (DWORD dwthread = 0; dwthread <g_threadcount; dwthread ++) {handle hthread; DWORD dwthreadid; hthread = createthread (null, 0, workerthread, 0, 0, & dwthreadid); closehandle (hthread) ;}{// accept new Conne Ction // load the acceptex function into memory using wsaioctl. // The wsaioctl function is an extension of the ioctlsocket () // function that can use overlapped I/O. the function's 3rd // through 6th parameters are input and output buffers Where // we pass the pointer to our acceptex function. this is used // so that we can call the acceptex function directly, rather // than refer to the mswsock. Lib library. guid guidacceptex = signature; DWORD dwbytes = 0; int iresult = wsaioctl (g_serversocket, signature, & guidacceptex, sizeof (guidacceptex), & signature, sizeof (signature), & dwbytes, null, null); If (iresult = socket_error) {wprintf (L "wsaioctl failed with error: % u \ n", wsagetlasterror (); closesocket (g_serversocket); wsacleanup (); return ;}// Delivery accept operation Enum {nmaxacceptrequest = 1,}; io_data * piodata = new io_data [nmaxacceptrequest]; memset (piodata, 0, sizeof (io_data) * nmaxacceptrequest ); for (INT xreq = 0; xreq <nmaxacceptrequest; xreq ++) {If (! Postacceptrequest (piodata + xreq) break;} // end of Post accept }}

2, 3 shipping functions,

2. A delivery accept request

bool PostAcceptRequest(IO_DATA * pIoData){    DWORD dwBytes = 0;    // Create an accepting socket    SOCKET AcceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    if (AcceptSocket == INVALID_SOCKET)     {        PUTLOG("Create accept socket failed with error: %u\n"                , WSAGetLastError());        return false;    }    // Empty our overlapped structure and accept connections.    memset(&pIoData->Overlapped, 0, sizeof(pIoData->Overlapped));    pIoData->opCode = IO_ACCEPT;    pIoData->activeSocket = AcceptSocket;    BOOL bRetVal = g_lpfnAcceptEx(g_ServerSocket        , AcceptSocket        , pIoData->RecvBuffer        , 0 //, sizeof(pIoData[nCocurrent].Buffer)            //  -((sizeof(sockaddr_in)+16)*2)        , sizeof (sockaddr_in) + 16        , sizeof (sockaddr_in) + 16        , &dwBytes        , &pIoData->Overlapped);    if (bRetVal == FALSE && GetLastError() != ERROR_IO_PENDING)     {        PUTLOG("AcceptEx failed with error: %u\n"                , WSAGetLastError());        closesocket(AcceptSocket);        return false;    }    // associate    if (NULL == (CreateIoCompletionPort((HANDLE) AcceptSocket                                        , g_hIOCP                                        , (u_long) 0                                        , 0)))     {        PUTLOG("CreateIoCompletionPort associate failed with error: %u\n"                , GetLastError());                        closesocket(AcceptSocket);        return false;    }    return true;}

3. B throws a Recv request

bool PostRecvRequest(IO_DATA * const ioReq, SOCKET sockfd){     IO_DATA * data = ioReq;     data->activeSocket = sockfd;     ZeroMemory(&data->Overlapped,sizeof(data->Overlapped));     data->opCode = IO_OPERATION(IO_READ);     data->wsabuf.buf  = data->RecvBuffer + data->dwRecved;     data->dwRecvBufTail = sizeof(data->RecvBuffer);     data->wsabuf.len  = data->dwRecvBufTail - data->dwRecved;     DWORD dwRecvNumBytes=0;     DWORD dwFlags=(MSG_PEEK & (~MSG_PEEK));     int nRet = WSARecv(data->activeSocket                     , &data->wsabuf                     , 1                     , &dwRecvNumBytes                     , &dwFlags                     , &data->Overlapped                     , NULL);     if(nRet == SOCKET_ERROR  && (ERROR_IO_PENDING != WSAGetLastError()))     {         PUTLOG("WASRecv Failed::Reason Code:: %u\n"                , WSAGetLastError());         return false;     }     return true;}

3. c throws a send request

bool PostSendRequest(IO_DATA * const ioReq, SOCKET sockfd){     IO_DATA * data = ioReq;     data->activeSocket = sockfd;     ZeroMemory(&data->Overlapped,sizeof(data->Overlapped));     data->opCode = IO_OPERATION(IO_SEND);     data->wsabuf.buf  = data->SendBuffer + data->dwSent;     data->wsabuf.len  = data->dwSendBufTail - data->dwSent;     DWORD dwSendNumBytes=0;     DWORD dwFlags=(MSG_PEEK & (~MSG_PEEK));     int nRet = WSASend(data->activeSocket                     , &data->wsabuf                     , 1                     , &dwSendNumBytes                     , dwFlags                     , &data->Overlapped                     , NULL);     if(nRet == SOCKET_ERROR  && (ERROR_IO_PENDING != WSAGetLastError()))     {         PUTLOG("WSASend Failed::Reason Code:: %u\n"                , WSAGetLastError());         return false;     }     return true;}

4. Working thread

DWORD winapi workerthread (lpvoid workthreadcontext) {for (;) {bool bsuccess = false; DWORD dwiosize = 0; void * lpcompletionkey = NULL; lpwsaoverlapped lpoverlapped = NULL; bsuccess = getqueuedcompletionstatus (g_hiocp, & dwiosize, (lpdword) & lpcompletionkey, (lpoverlapped *) & lpoverlapped, infinite); If (! Bsuccess) {putlog ("getqueuedcompletionstatus () failed: % u \ n", getlasterror ();} io_data * lpiocontext = (io_data *) lpoverlapped; // new socket connection up if (lpiocontext-> opcode = io_accept) // a read operation complete {// update the socket status int errorcode = setsockopt (lpiocontext-> activesocket, sol_socket, so_update_accept_context, (char *) & g_serversocket, sizeof (g_serversocket); // submit the Read Request io_data * Data = New io_data; If (data) {postrecvrequest (data, lpiocontext-> activesocket);} else {closesocket (data-> activesocket); data-> activesocket = invalid_socket; delete data;} // submit a new accept postacceptrequest (lpiocontext); continue;} If (dwiosize = 0) // socket closed? {Putlog ("client dis-connected. \ n "); closesocket (lpiocontext-> activesocket); lpiocontext-> activesocket = invalid_socket; continue;} // read completed if (lpiocontext-> opcode = io_read) {// reset the timeout lpiocontext-> dwentertick = gettickcount (); // accumulate the total length of the Request lpiocontext-> dwrecved + = dwiosize; bool isreqready = true; //// if the data packet has been read, /// start processing. // after processing, send the request ////... if (isreqready) {lpiocontext-> dwsent = 0; lpiocontext-> dwsendbuftail = 0; memcpy (lpiocontext-> sendbuffer + lpiocontext-> dwsendbuftail, "\ r \ n \ r \ nserverecho:", 16); lpiocontext-> protocol + = 16; memcpy (lpiocontext-> sendbuffer + lpiocontext-> dwsendbuftail, lpiocontext-> recvbuffer, lpiocontext-> dwrecved); lpiocontext-> signature + = lpiocontext-> dwrecved; memcpy (lpiocontext-> sendbuffer + lpiocontext-> signature, "\ r \ n ", 4); lpiocontext-> dwsendbuftail + = 4; postsendrequest (lpiocontext, lpiocontext-> activesocket );} //// if the read is not completed // continue shipping the Read Request ////... else {postrecvrequest (lpiocontext, lpiocontext-> activesocket);} continue;} // If (lpiocontext-> opcode = io_send) {// reset timeout lpiocontext-> dwentertick = gettickcount (); lpiocontext-> dwsent + = dwiosize; bool isrespready = (lpiocontext-> dwsent = lpiocontext-> timeout ); //// if the data packet is sent, // after the call is started, // after the request is sent, the read request is sent ////... if (isrespready) {lpiocontext-> dwrecved = 0; lpiocontext-> Signature = sizeof (lpiocontext-> recvbuffer); postrecvrequest (lpiocontext, lpiocontext-> activesocket );} //// if the request is not sent, /// send another request ////... else {postsendrequest (lpiocontext, lpiocontext-> activesocket) ;}continue ;}} return 0 ;}

5. Start with a main program to see the effect.

int main(int argc, char * argv []){    ListenThread(NULL);        PUTLOG("Press any key to quit server.");    getchar();    return 0;}

Output:

========================================================== ==================================

Download project files:

Http://hi.csdn.net/attachment/201112/26/0_1324859981Zd6C.gif

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.