多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 互聯網 > 網絡編程(56)—— Windows下使用IOCP構建socket服務端

網絡編程(56)—— Windows下使用IOCP構建socket服務端

來源:程序員人生   發布時間:2017-02-05 13:46:10 閱讀次數:3472次

1、完成端口對象

        不同于IO堆疊對象在IO完成時通過觸發事件或觸發CompletionRoutine回調函數,IOCP模型將socket和完成端口對象(CompletionPort,簡稱CP對象)綁定,當IO操作完成時,會改變該對象的狀態,而我們通過完成端口對象,即可以確認IO操作是不是完成。

       創建完成端口對象的API以下:

HANDLE WINAPI CreateIoCompletionPort(
  __in     HANDLE FileHandle,
  __in_opt HANDLE ExistingCompletionPort,
  __in     ULONG_PTR CompletionKey,
  __in     DWORD NumberOfConcurrentThreads
);

CreateIoCompletionPort既可以創建完成端口對象,也能夠用來將socket和完成對象綁定,通過對其賦予不同的參數,可以實現不同的功能:

FileHandle ——創建CP對象時傳入INVALID_HANDLE_VALUE;綁定socket和CP對象時傳入socket描寫符。

ExistingCompletionPort——創建CP對象時傳入NULL;綁定socket和CP對象傳入完成端口對象的句柄;

CompletionKey —— 創建CP對象是傳入0;綁定socket和CP對象時作為參數傳遞給GetQueuedCompletionStatus

NumberOfConcurrentThreads—— 分配給CP對象用于處理IO的線程數。如果參數是0,系統中的CPU個數就是最大的線程數。

返回值 —— 返回CP對象的句柄。

        以下,我們創建了1個完成端口對象:

hComPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);

2、進行socket對象和CP對象的綁定

        我們依然用CreateIoCompletionPort將socket和CP對象進行綁定:

CreateIoCompletionPort((HANDLE)clntSock,hComPort,(DWORD)handleInfo,0);

        clntSock是我們要進行綁定的socket描寫符,hComPort使我們之前創建的CP對象,而handleInfo是我們自定義的結構體,作為參數可以傳給GetQueuedCompletionStatus函數。

3、使用GetQueuedCompletionStatus獲得CP對象的狀態

        GetQueuedCompletionStatus在我們定義的線程函數中調用,用于獲得CP對象的狀態。當IO操作未完成時,該函數會產生阻塞;若IO操作完成,函數產生返回。其函數原型以下:

BOOL WINAPI GetQueuedCompletionStatus(
  __in  HANDLE CompletionPort,
  __out LPDWORD lpNumberOfBytes,
  __out PULONG_PTR lpCompletionKey,
  __out LPOVERLAPPED *lpOverlapped,
  __in  DWORD dwMilliseconds
);

CompletionPort —— 進行注冊過的完成對象的句柄。

lpNumberOfBytes —— 完成IO對象時傳遞或接受的字節數。

lpCompletionKey —— 使用CreateIoCompletionPort注冊時傳遞的參數,參數可以傳遞我們自定義的結構信息。

lpOverlapped —— 調用WSARecv或WSASend時傳遞的OVERLAPPED對象指針。

dwMilliseconds —— GetQueuedCompletionStatus阻塞的時間,如果設置成INFINITE時無窮期等待。

4、代碼示例

#include "stdafx.h"
#include "stdio.h"
#include "process.h"
#include "stdlib.h"
#include "WinSock2.h"
#include "Windows.h"
 
#pragma comment(lib,"ws2_32.lib")
 
#define BUF_SIZE 100
#define READ 3
#define WRITE 5
 
typedef struct 
{
    SOCKEThClntSock;
    SOCKADDRclntAdr;
}HANDLE_DATA,*LPHANDLE_DATA;
 
typedef struct
{
    OVERLAPPEDoverlapped;
    WSABUFwsaBuf;
    char buffer[BUF_SIZE];
    int rwMode;
}IO_DATA,*LPIO_DATA;
 
unsigned WINAPI ThreadMain(LPVOID CompletionPortIO);
void ErrorHandler(char* message);
 
int _tmain(int argc, _TCHAR* argv[])
{
    WSADatawsaData;
    HANDLEhComPort;
    SYSTEM_INFOsysInfo;
    LPIO_DATAioInfo;
    LPHANDLE_DATAhandleInfo;
 
    SOCKETservSock;
    SOCKADDR_INservAddr;
    DWORDrecvBytes,i,flags=0;
    WSAStartup(MAKEWORD(2,2),&wsaData);
   
    hComPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
    GetSystemInfo(&sysInfo);
 
    for(i=0;i<sysInfo.dwNumberOfProcessors;i++)
        _beginthreadex(NULL,0,ThreadMain,(LPVOID)hComPort,0,NULL);
 
    servSock=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
    if(servSock==INVALID_SOCKET)
        ErrorHandler("WSASocket Error");
 
    memset(&servAddr,0,sizeof(servAddr));
    servAddr.sin_family=AF_INET;
    servAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    servAddr.sin_port=htons(atoi("8888"));
 
    if(bind(servSock,(SOCKADDR*)&servAddr,sizeof(servAddr))==SOCKET_ERROR)
        ErrorHandler("bind error");
 
    if(listen(servSock,5)==SOCKET_ERROR)
        ErrorHandler("listen error");
 
    while(1)
    {
        SOCKETclntSock;
        SOCKADDR_INclntAddr;
        int clntAddrSz;
 
        clntSock=accept(servSock,(SOCKADDR*)&clntAddr,&clntAddrSz);
        handleInfo=(LPHANDLE_DATA)malloc(sizeof(HANDLE_DATA));
        handleInfo->hClntSock=clntSock;
        memcpy(&(handleInfo->clntAdr),&clntAddr,sizeof(clntAddr));
 
        CreateIoCompletionPort((HANDLE)clntSock,hComPort,(DWORD)handleInfo,0);
 
        ioInfo=(LPIO_DATA)malloc(sizeof(IO_DATA));
        memset(&(ioInfo->overlapped),0,sizeof(OVERLAPPED));
        ioInfo->wsaBuf.len=BUF_SIZE;
        ioInfo->wsaBuf.buf=ioInfo->buffer;
        ioInfo->rwMode=READ;
        WSARecv(handleInfo->hClntSock,&(ioInfo->wsaBuf),1,&recvBytes,&flags,&(ioInfo->overlapped),NULL);
    }
   
    WSACleanup();
    return 0;
}
 
unsigned WINAPI ThreadMain(LPVOID CompletionPortIO)
{
    HANDLEhComPort=(HANDLE)CompletionPortIO;
    SOCKET sock;
    DWORDbytesTrans;
    LPHANDLE_DATAhandleInfo;
    LPIO_DATAioInfo;
    DWORD flags;
 
    while(1)
    {
    GetQueuedCompletionStatus(hComPort,&bytesTrans,(PULONG_PTR)&handleInfo,(LPOVERLAPPED*)&ioInfo,INFINITE);
        sock=handleInfo->hClntSock;
 
        if(ioInfo->rwMode==READ)
        {
            puts("message received!");
            if(bytesTrans==0)
            {
                closesocket(sock);
                free(handleInfo);
                free(ioInfo);
                continue;
            }
            memset(&(ioInfo->overlapped),0,sizeof(OVERLAPPED));
            ioInfo->wsaBuf.len=bytesTrans;
            ioInfo->rwMode=WRITE;
            WSASend(sock,&(ioInfo->wsaBuf),1,NULL,0,&(ioInfo->overlapped),NULL);
 
            ioInfo=(LPIO_DATA)malloc(sizeof(IO_DATA));
            memset(&(ioInfo->overlapped),0,sizeof(OVERLAPPED));
            ioInfo->wsaBuf.len=BUF_SIZE;
            ioInfo->wsaBuf.buf=ioInfo->buffer;
            ioInfo->rwMode=READ;
            WSARecv(sock,&(ioInfo->wsaBuf),1,NULL,&flags,&(ioInfo->overlapped),NULL);
        }
        else
        {
            puts("message sent");
            free(ioInfo);
        }
    }
    return 0;
}
 
void ErrorHandler(char* message)
{
    fputs(message,stderr);
    fputc('\n',stderr);
    exit(1);
}


 Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本項目:
git clone git@github.com:HymanLiuTS/NetDevelopment.git
獲得本文源代碼:
git checkout NL56


生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 天天澡天天碰天天狠伊人五月 | 久草福利在线播放 | 精品视频亚洲 | 欧美日韩国产在线观看 | 欧美成人看片一区二区三区尤物 | 国产精品欧美一区二区 | 手机看片成人 | 一二三四在线手机观看视频 | 欧美亚洲一区二区三区 | 五月网| 来吧成人综合网 | 欧美国产日韩1区俺去了 | 亚洲天天综合 | 最近中文字幕国语完整视频 | 曰本www| 日本一区二区三区不卡视频中文字幕 | 亚洲美女又黄又爽在线观看 | 欧美一级毛片日韩一级 | 亚洲国产精品第一区二区 | 久久久久国产一级毛片高清版 | 亚洲综合久久综合激情久久 | 精品91一区二区三区 | 亚洲自拍偷拍专区 | 欧美白人黑人xxxx猛交 | 久久精品久久精品国产大片 | 欧美另类亚洲 | 国产成人综合网亚洲欧美在线 | 欧美精品videos | 国产毛片片精品天天看视频 | 亚洲ass| 在线观看国产情趣免费视频 | 日本a中文字幕 | 国产福利资源在线 | 欧美综合国产精品日韩一 | 手机看片午夜 | 成人久久久精品乱码一区二区三区 | 国产精品人成 | 久久国产一久久高清 | 亚洲精品第一页 | 五月天校园春色 | 亚洲欧美精品一中文字幕 |