青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 298  文章 - 377  trackbacks - 0
<2017年4月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用鏈接

留言簿(34)

隨筆分類

隨筆檔案

文章檔案

相冊

收藏夾

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

以前在書上看過了IOCP,不過一直都沒有寫過代碼?,F(xiàn)在寫的時候,著時對很多問題摸不著頭腦。不過好在CSDN上有許多的對于IOCP問題的討論帖,讓我受益非淺啊,也把心中的一些迷茫解開了,下面給出的是可以運行的IOCP的C/S代碼,自已試了在一個機器上開了一百來個客戶端,跑起來暫時沒出現(xiàn)問題(因為通信內(nèi)容太簡單了^-^)。

IOCP的三個函數(shù):CreateIoCompletionPort、GetQueuedCompletionStatus、PostQueuedCompletionStatus;一個是用來創(chuàng)建想要的IOCP的HANDLE同時也是用來把我們想要的SOCKET綁定到這個HANDLE上,一個是獲取IO這個HANDLE上對應(yīng)的對列的狀態(tài),看有沒有事件完成,一個是用來通知所有工作線程退出(這個函數(shù)我還沒用到,關(guān)于這個功用是看資料上說的)。

我在寫這個代碼的時候,最主要的問題就是當通信完成了之后,是怎么樣來判斷是哪個SOCKET的哪個狀態(tài)(SEND還是RECV)完成了?!禬INDOWS網(wǎng)絡(luò)編程》這本書里給的代碼不是很全的哦,它的配套光盤又沒有,不過好在CSDN里CB那塊中有個朋友剛好帖出了這一章的代碼。通過比較和一夜的思量,算是搞明白啦。主要的就是以下的數(shù)據(jù):

1、在第二次CreateIoCompletionPort中,會傳進去一個CompletionKey,這個就是要來關(guān)聯(lián)到我們想要的SOCKET上的一些感興趣的數(shù)據(jù)內(nèi)容,當然最好是要一個SOCKET,也可以是其它,看自己程序的需要了。而通過GetQueueCompletionStatus的通過,就可以獲得這些數(shù)據(jù)的地址了。

typedef struct _PER_HANDLE_DATA
{
    SOCKET sock;
}PER_HANDLE_DATA,* LPPER_HANDLE_DATA;

2、第二個主要的數(shù)據(jù)結(jié)構(gòu)就是這個了,現(xiàn)在真的是佩服當初設(shè)計這個結(jié)構(gòu)的人?。]辦法,自己就是沒想到這樣利用法)。因為在POST操作(SEND或是RECV)是,都要一個OVERLAPPED,所以就把這個OVERLAPPED和要指明這次POST操作類型的代碼OperationType(POST_SEND或POST_RECV)以及其它一些數(shù)據(jù)(比如接發(fā)收的緩沖)。這樣子,在GetQueueCompletionStatus的時候,通過獲取事件,也同時得到了OperationType和緩沖。這樣,知道了通信類型,也得到了緩沖數(shù)據(jù)的緩沖區(qū)。這樣就可以控制我們的通信了。

這個例子比較簡單,沒有復(fù)雜的數(shù)據(jù)處理過程(正在設(shè)計中,和大家交流交流)。用的是BCB的平臺,不過寫法上還是和VC里的一模一樣的啊。

typedef struct _PER_IO_OPERATION_DATA
{
    OVERLAPPED Overlapped;
    WSABUF DataBuff[1];
    char Buff[24];
    BOOL OperationType;
}PER_IO_OPERATION_DATA,* LPPER_IO_OPERATION_DATA;

簡單的客戶端:

//---------------------------------------------------------------------------

#pragma hdrstop
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------

#pragma argsused

SOCKET sockClient;
struct sockaddr_in addrServer;
char buf[24];
int n = 0;
int Init();

int main(int argc, char* argv[])
{
    if(Init() != 0)
        goto theend;

    sockClient = socket(AF_INET,SOCK_STREAM,0);
    if(sockClient == INVALID_SOCKET)
    {
        cout<<"socket 失敗"<<endl;
        WSACleanup();
        goto theend;
    }
    memset(&addrServer,0,sizeof(sockaddr_in));
    addrServer.sin_family = AF_INET;
    addrServer.sin_addr.s_addr = inet_addr("127.0.0.1");
    addrServer.sin_port = htons(9090);
    cout<<"連接服務(wù)器..."<<endl;
    if(connect(sockClient,(const struct sockaddr *)&addrServer,sizeof(sockaddr)) != 0)
    {
        cout<<"connect 失敗"<<endl;
        WSACleanup();
        goto theend;
    }
    cout<<"開始發(fā)送測試包"<<endl;
    memset(buf,0,24);
    while(true)
    {
        sprintf(buf,"第%d個包", n);
        cout<<"發(fā)送:"<<buf<<endl;
        if(send(sockClient,buf,strlen(buf),0) <= 0)
        {
            cout<<"send失敗,可能連接斷開"<<endl;
            //break;
            goto theend;
        }
        memset(buf,0,24);

        //接收服務(wù)端應(yīng)答
        if(recv(sockClient,buf,24,0) <= 0)
        {
            cout<<"recv失敗,可能連接斷開"<<endl;
           //break;
           goto theend;
        }
        cout<<"服務(wù)器應(yīng)答:"<<buf<<endl;
        memset(buf,0,24);

        Sleep(200);
        n++;
    }

   
theend:
    WSACleanup();
    getchar();
    return 0;
}
//---------------------------------------------------------------------------
int Init()
{
    WSAData wsaData;
    if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
    {
        cout<<"WSAStartup失敗"<<endl;
        return -1;
    }

    if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        cout<<"SOCKET版本不對"<<endl;
        WSACleanup();
        return -1;
    }
    return 0;
}

服務(wù)端。

//---------------------------------------------------------------------------

#pragma hdrstop

//---------------------------------------------------------------------------
#pragma argsused
#pragma comment(lib,"ws2_32.lib")
#include <stdio.h>
#include <memory.h>
#include <winsock2.h>
#include <iostream>
using namespace std;

#define RECV_POSTED 1001
#define SEND_POSTED 1002

int Init();

HANDLE hCompletionPort;
typedef struct _PER_HANDLE_DATA
{
    SOCKET sock;
}PER_HANDLE_DATA,* LPPER_HANDLE_DATA;

typedef struct _PER_IO_OPERATION_DATA
{
    OVERLAPPED Overlapped;
    WSABUF DataBuff[1];
    char Buff[24];
    BOOL OperationType;
}PER_IO_OPERATION_DATA,* LPPER_IO_OPERATION_DATA;

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPort);

int main(int argc, char* argv[])
{
    LPPER_HANDLE_DATA perHandleData;
    LPPER_IO_OPERATION_DATA ioperdata;
    SYSTEM_INFO siSys;
    SOCKET sockListen;
    struct sockaddr_in addrLocal;
    char buf[24];
    int nRet = 0;
    DWORD nThreadID;
    SOCKET sockAccept;
    DWORD dwFlags;
    DWORD dwRecvBytes;
    int nReuseAddr = 1;

    cout<<"初始環(huán)境..."<<endl;
    if(Init() != 0)
        goto theend;

    //創(chuàng)建一個IO完成端口
    cout<<"創(chuàng)建一個IO完成端口"<<endl;
    hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
    if(hCompletionPort == INVALID_HANDLE_VALUE)
    {
        cout<<"創(chuàng)建IO完成端口失敗"<<endl;
        goto theend;
    }
    //獲取CPU數(shù)目
    GetSystemInfo(&siSys);
    //創(chuàng)建一定數(shù)目的工作者線程,本例中以一個處理器一個線程搭配
    for(int i = 0;i<(int)siSys.dwNumberOfProcessors*2;i++)//NumberOfProcessors
    {
        HANDLE hThread;
        hThread = CreateThread(NULL,0,ServerWorkerThread,(LPVOID)hCompletionPort,0,&nThreadID);
        cout<<"創(chuàng)建工作者線程"<<i<<endl;
        CloseHandle(hThread);
    }
    //創(chuàng)建監(jiān)聽SOCKET
    cout<<"創(chuàng)建監(jiān)聽SOCKET"<<endl;
    sockListen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
    if(sockListen == SOCKET_ERROR)
    {
        cout<<"WSASocket錯誤"<<endl;
        goto theend;
    }

    if(setsockopt(sockListen,SOL_SOCKET,SO_REUSEADDR,(const char *)&nReuseAddr,sizeof(int)) != 0)
    {
        cout<<"setsockopt錯誤"<<endl;
        goto theend;
    }
    addrLocal.sin_family = AF_INET;
    addrLocal.sin_addr.s_addr = htonl(INADDR_ANY);
    addrLocal.sin_port = htons(9090);
    if(bind(sockListen,(struct sockaddr *)&addrLocal,sizeof(sockaddr_in)) != 0)
    {
        cout<<"bind錯誤"<<endl;
        int n = WSAGetLastError();
        goto theend;
    }
    //準備監(jiān)聽
    cout<<"準備監(jiān)聽"<<endl;
    if(listen(sockListen,5)!=0)
    {
        cout<<"listen錯誤"<<endl;
        goto theend;
    }
    while(true)
    {
        //接收用戶連接,被和完成端口關(guān)聯(lián)
        sockAccept = WSAAccept(sockListen,NULL,NULL,NULL,0);
        perHandleData = (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));
        if(perHandleData == NULL)
            continue;
        cout<<"socket number "<<sockAccept<<"接入"<<endl;
        perHandleData->sock = sockAccept;

        ioperdata = (LPPER_IO_OPERATION_DATA)malloc(sizeof(PER_IO_OPERATION_DATA));
        memset(&(ioperdata->Overlapped),0,sizeof(OVERLAPPED));
        (ioperdata->DataBuff[0]).len = 24;
        (ioperdata->DataBuff[0]).buf = ioperdata->Buff;
        ioperdata->OperationType = RECV_POSTED;
        if( ioperdata == NULL)
        {
            free(perHandleData);
            continue;
        }
        //關(guān)聯(lián)
        cout<<"關(guān)聯(lián)SOCKET和完成端口"<<endl;
        if(CreateIoCompletionPort((HANDLE)sockAccept,hCompletionPort,(DWORD)perHandleData,1) == NULL)
        {
            cout<<sockAccept<<"createiocompletionport錯誤"<<endl;
            free(perHandleData);
            free(ioperdata);
            continue;
        }
        //投遞接收操作
        cout<<"投遞接收操作"<<endl;
        WSARecv(perHandleData->sock,ioperdata->DataBuff,1,&dwRecvBytes,&dwFlags,&(ioperdata->Overlapped),NULL);
    }
theend:
    getchar();
    return 0;
}
//---------------------------------------------------------------------------
int Init()
{
    WSAData wsaData;
    if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
    {
        cout<<"WSAStartup失敗"<<endl;
        return -1;
    }

    if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        cout<<"SOCKET版本不對"<<endl;
        WSACleanup();
        return -1;
    }
    return 0;
}

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPort)
{
    HANDLE ComPort = (HANDLE)CompletionPort;
    DWORD BytesTransferred;
    LPOVERLAPPED Overlapped;
    LPPER_HANDLE_DATA PerHandleData;
    LPPER_IO_OPERATION_DATA PerIoData;
    DWORD SendBytes,RecvBytes;
    DWORD Flags;
    BOOL bT;

    while(TRUE)
    {
        //等待完成端口上SOCKET的完成
        cout<<"等待完成端口上SOCKET的完成"<<endl;
        bT = GetQueuedCompletionStatus(ComPort,
            &BytesTransferred,(LPDWORD)&PerHandleData,
            (LPOVERLAPPED *)&PerIoData,INFINITE);

        //檢查是否有錯誤產(chǎn)生
        if(BytesTransferred == 0 &&
            (PerIoData->OperationType == RECV_POSTED ||
            PerIoData->OperationType == SEND_POSTED))
        {
            //關(guān)閉SOCKET
            cout<<PerHandleData->sock<<"SOCKET關(guān)閉"<<endl;
            closesocket(PerHandleData->sock);
            free(PerHandleData);
            free(PerIoData);
            continue;
        }

        //為請求服務(wù)
       
        if(PerIoData->OperationType == RECV_POSTED)
        {
            //處理
            cout<<"接收處理"<<endl;
            cout<<PerHandleData->sock<<"SOCKET :"<<PerIoData->Buff<<endl;
            //回應(yīng)客戶端
            ZeroMemory(PerIoData->Buff,24);
            strcpy(PerIoData->Buff,"OK");
            Flags = 0;
            ZeroMemory((LPVOID)&(PerIoData->Overlapped),sizeof(OVERLAPPED));
            PerIoData->DataBuff[0].len = 2;
            PerIoData->DataBuff[0].buf = PerIoData->Buff;
            PerIoData->OperationType = SEND_POSTED;
            WSASend(PerHandleData->sock,PerIoData->DataBuff,
                1,&SendBytes,0,&(PerIoData->Overlapped),NULL);
        }
        else //if(PerIoData->OperationType == SEND_POSTED)
        {
            //發(fā)送時的處理
            cout<<"發(fā)送處理"<<endl;
            Flags = 0;
            ZeroMemory((LPVOID)&(PerIoData->Overlapped),sizeof(OVERLAPPED));
            ZeroMemory(PerIoData->Buff,24);
            PerIoData->DataBuff[0].len = 24;
            PerIoData->DataBuff[0].buf = PerIoData->Buff;
            PerIoData->OperationType = RECV_POSTED;
            WSARecv(PerHandleData->sock,PerIoData->DataBuff,
                1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
        }
    }
}


posted on 2007-08-17 11:55 聶文龍 閱讀(14566) 評論(7)  編輯 收藏 引用 所屬分類: net work

FeedBack:
# re: IOCP的例子  2010-07-04 16:03 adsads
請教下:
WSARecv(perHandleData->sock,ioperdata->DataBuff,1,&dwRecvBytes,&dwFlags,&(ioperdata->Overlapped),NULL);

我碰到幾個問題:

1、IO投遞,WSARecv,是異步IO,還是同步 我就是想知道你是怎么投遞的

是不是一調(diào)用中廣核WSARecv就馬上能夠返回的嗎?

2、關(guān)聯(lián)數(shù)據(jù)CreateIoCompletionPort()為什么 我在XP上寫的代碼 這個函數(shù) 在 在關(guān)聯(lián)數(shù)據(jù)的時候,總是失敗呢?錯誤是87 參數(shù)不正確,但我按照其他人寫的代碼,結(jié)果全是一樣


如果你真的在實戰(zhàn)中使用過,我向你請教,希望你不吝賜教



  回復(fù)  更多評論
  
# re: IOCP的例子  2010-07-04 16:05 adsads
還是管IO投遞

如果你調(diào)用WSARecv函數(shù)投遞,如果這個函數(shù)一直堵塞在這里,那談何效率


如果你真的是做到異步IO的話,希望你能幫我下


因為這個問題,困擾我很久了

就是說:

如何在IOCP中,使用異步IO


  回復(fù)  更多評論
  
# re: IOCP的例子 [未登錄] 2013-02-28 19:41 Fairy
在我的機子上 怎么不行 wsarecv總是返回10045   回復(fù)  更多評論
  
# re: IOCP的例子  2013-06-04 14:54 tankin
@Fairy
Flag 要修改成 0
因為是一個[in][out] 值  回復(fù)  更多評論
  
# re: IOCP的例子  2013-11-11 17:12 good90
WSARecv中dwFlags lz都不初始。。  回復(fù)  更多評論
  
# re: IOCP的例子  2013-11-22 12:38 路過的
這代碼 簡直是誤導(dǎo)人 在WSAAccept 這里就開始一直在阻塞主線程了 你還怎么異步  回復(fù)  更多評論
  
# re: IOCP的例子  2014-11-30 16:16 apc
@路過的
主線程主要處理連接,沒有連接時線程掛起,收、發(fā)在工作線程,這怎么不是異步  回復(fù)  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              国产精品视频专区| 亚洲日本成人| 猫咪成人在线观看| 亚洲欧美一区二区三区在线 | 久久精品亚洲精品| 久久成人羞羞网站| 久久深夜福利| 免费中文字幕日韩欧美| 欧美国产日韩在线观看| 亚洲肉体裸体xxxx137| 亚洲天堂第二页| 久久激情久久| 欧美精品乱码久久久久久按摩| 欧美三级网址| 国内精品写真在线观看| 日韩一区二区福利| 久久精品伊人| 亚洲精品久久在线| 久久久99国产精品免费| 欧美日韩国产综合久久| 国产伊人精品| 亚洲自拍啪啪| 亚洲国产精品久久人人爱蜜臀| 亚洲欧美国产日韩天堂区| 欧美成人一区二区三区| 国产日韩1区| 一区二区三区福利| 免费观看国产成人| 亚洲欧美日韩人成在线播放| 欧美日韩ab片| 在线看日韩av| 亚洲人成高清| 你懂的视频一区二区| 欧美在线一二三区| 99香蕉国产精品偷在线观看| 欧美人与禽性xxxxx杂性| 在线观看成人av| 亚洲国产精品传媒在线观看 | 久久精品国产亚洲aⅴ| 亚洲日本一区二区| 欧美日韩国产电影| 亚洲人成久久| 亚洲摸下面视频| 亚洲欧美国产77777| 亚洲欧美在线另类| 久久久国产精彩视频美女艺术照福利| 欧美激情在线| 久久精品欧美| 国产一本一道久久香蕉| 亚洲综合社区| 一区二区欧美日韩| 欧美精品色综合| 亚洲第一区在线| 久久久免费观看视频| 亚洲欧美在线视频观看| 欧美日韩一二三四五区| 日韩一区二区免费看| 欧美国产日韩在线| 奶水喷射视频一区| 亚洲福利视频网| 欧美电影打屁股sp| 久久综合国产精品| 在线看日韩av| 亚洲电影免费在线 | 欧美一区二区三区久久精品 | 欧美一区国产一区| 国内伊人久久久久久网站视频 | 亚洲一区在线直播| 亚洲欧美成人精品| 国产一区清纯| 亚洲专区一区二区三区| 久久精品盗摄| 欧美在线免费视屏| 精品88久久久久88久久久| 美女脱光内衣内裤视频久久影院 | 亚洲在线视频观看| 亚洲一卡二卡三卡四卡五卡| 国产女主播一区| 美女精品一区| 欧美精品二区| 欧美亚洲一区三区| 久久久久久电影| 洋洋av久久久久久久一区| 亚洲网站在线观看| 伊人色综合久久天天五月婷| 亚洲人午夜精品免费| 国产精品视频99| 免费日韩av电影| 欧美日本一区| 在线性视频日韩欧美| 亚洲综合导航| 亚洲激情国产| 亚洲一区二区久久| 亚洲激情影视| 午夜精品一区二区三区在线| 91久久精品国产| 亚洲视频在线观看| 亚洲国产另类精品专区| 亚洲网在线观看| 亚洲欧洲另类国产综合| 午夜日本精品| 亚洲特色特黄| 欧美成人精品h版在线观看| 午夜精品久久久久久久| 久久这里只有| 久久精品国产成人| 欧美少妇一区二区| 欧美激情一区二区| 黄色精品在线看| 亚洲男人第一av网站| 一区二区日韩欧美| 美女被久久久| 久热这里只精品99re8久| 国产精品综合av一区二区国产馆| 亚洲人成网站色ww在线| 亚洲第一网站免费视频| 久久不射网站| 久久精品免费看| 国产日韩欧美在线看| 亚洲一区久久久| 亚洲一区亚洲| 欧美天堂在线观看| 日韩亚洲国产精品| 一区二区久久久久| 欧美人与禽猛交乱配视频| 亚洲国产aⅴ天堂久久| 在线国产精品一区| 久久影院午夜论| 欧美成人一区二免费视频软件| 精品999网站| 久久亚洲精品欧美| 女人色偷偷aa久久天堂| 在线欧美日韩精品| 欧美va亚洲va日韩∨a综合色| 欧美成人自拍| 亚洲乱码视频| 欧美午夜精品一区二区三区| 99re成人精品视频| 亚洲午夜久久久久久久久电影院 | 亚洲欧美激情四射在线日| 国产精品久久九九| 亚洲砖区区免费| 久久久久久国产精品mv| 伊人久久噜噜噜躁狠狠躁| 久久伊伊香蕉| 亚洲国产专区| 亚洲永久精品大片| 国产一区二区日韩精品| 久久久久久久999| 亚洲激情电影在线| 亚洲一级二级| 国产一区二区三区网站| 麻豆免费精品视频| 一区二区毛片| 亚洲国产一区二区三区在线播| 亚洲精品久久久蜜桃| 欧美日韩一区二区三区免费| 亚洲香蕉伊综合在人在线视看| 亚洲视频欧美视频| 国产一区二区成人久久免费影院| 久久久久久久激情视频| 亚洲精品乱码久久久久| 亚洲欧美日韩综合| 国语自产精品视频在线看一大j8| 欧美高清视频www夜色资源网| 中文高清一区| 蜜桃av一区| 亚洲男人的天堂在线aⅴ视频| 狠狠做深爱婷婷久久综合一区| 欧美精品97| 久久久夜精品| 亚洲调教视频在线观看| 玖玖视频精品| 亚洲欧美日韩高清| 最新成人在线| 国产一区二区日韩精品| 欧美日韩亚洲一区二区三区四区| 久久成人精品电影| 一本一道久久综合狠狠老精东影业| 久久九九国产| 亚洲欧美成人| 夜夜嗨av一区二区三区网站四季av| 国产精品网站在线播放| 欧美国产综合视频| 久久精品99国产精品日本| 99精品免费| 亚洲激情视频网站| 蜜臀91精品一区二区三区| 亚洲欧美中文日韩v在线观看| 亚洲清纯自拍| 亚洲国产va精品久久久不卡综合| 国产美女一区二区| 欧美先锋影音| 欧美日本在线观看| 欧美成人久久| 另类尿喷潮videofree| 久久久av水蜜桃| 欧美一区二区成人| 亚洲欧美国产精品桃花| 亚洲特级片在线|