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

隨筆 - 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>
              欧美婷婷六月丁香综合色| 欧美福利一区二区| 一本大道久久a久久综合婷婷 | 免播放器亚洲一区| 久久精品99久久香蕉国产色戒| 国产日韩精品综合网站| 久久视频精品在线| 免费日韩成人| 亚洲免费影视| 欧美一区二区三区久久精品茉莉花| 国产一区二区三区日韩欧美| 蜜桃精品一区二区三区| 欧美国产精品中文字幕| 亚洲欧美一区二区激情| 久久高清国产| 日韩一区二区精品视频| 亚洲午夜精品久久久久久app| 国语自产偷拍精品视频偷| 亚洲电影观看| 欧美激情国产精品| 欧美一区二区三区视频在线观看 | 亚洲国产精品成人久久综合一区 | 午夜精品一区二区在线观看 | 国产一区二区三区奇米久涩| 亚洲成色777777在线观看影院| 欧美日韩另类字幕中文| 久久免费精品视频| 欧美日韩中文字幕综合视频| 久久午夜精品一区二区| 欧美视频福利| 欧美黄污视频| 国产中文一区二区| 99精品视频一区二区三区| 好吊色欧美一区二区三区四区| 亚洲久久视频| 一区二区三区**美女毛片| 欧美国产日本韩| 国产精品高清免费在线观看| 欧美va亚洲va香蕉在线| 国产精品入口夜色视频大尺度| 欧美激情国产日韩| 国产亚洲精品福利| 一区二区欧美精品| 亚洲日本欧美天堂| 久久久久九九九| 欧美一区二区大片| 欧美日韩伦理在线| 亚洲国产日韩一级| 在线观看成人小视频| 亚洲欧美中文日韩v在线观看| 中文国产亚洲喷潮| 欧美成人在线免费观看| 久久综合免费视频影院| 国产深夜精品| 亚洲女人天堂av| 亚洲欧美美女| 国产精品不卡在线| 一本色道**综合亚洲精品蜜桃冫| 亚洲欧洲偷拍精品| 猫咪成人在线观看| 欧美成人dvd在线视频| 狠狠综合久久av一区二区老牛| 午夜久久久久| 欧美在线一二三| 国产农村妇女毛片精品久久莱园子| 9国产精品视频| 亚洲午夜羞羞片| 欧美午夜片在线观看| 一区二区三区精密机械公司| 亚洲性图久久| 国产精品成人aaaaa网站| 一区二区三区精品视频在线观看| 国产精品99久久久久久人| 欧美天天影院| 亚洲免费视频网站| 久久久www成人免费无遮挡大片| 国产欧美一区二区精品秋霞影院 | 欧美成人精品在线观看| 亚洲国产1区| 欧美精品在线观看播放| 99视频在线观看一区三区| 午夜精品一区二区三区四区| 国产欧美精品一区二区三区介绍| 欧美一级久久久久久久大片| 久热精品视频在线观看一区| 亚洲国产免费看| 欧美喷潮久久久xxxxx| 亚洲视频在线一区| 卡通动漫国产精品| 亚洲精品一区二区三区四区高清| 欧美日韩国产丝袜另类| 亚洲欧美日韩人成在线播放| 欧美jjzz| 亚洲欧美日韩在线播放| 一区在线视频观看| 欧美日产国产成人免费图片| 午夜精品久久久久久久99樱桃| 久热精品视频在线观看| 国产精品99久久久久久久vr| 国产日韩在线一区| 麻豆av福利av久久av| 亚洲欧洲一区二区三区久久| 亚洲免费在线电影| 亚洲第一页自拍| 国产精品九九| 欧美成人69av| 性久久久久久久久| 亚洲三级免费| 久久夜色精品一区| 亚洲免费在线看| 亚洲经典一区| 国产一区二区你懂的| 欧美日韩免费区域视频在线观看| 午夜精品免费在线| 亚洲毛片在线看| 欧美成人日韩| 久久米奇亚洲| 亚洲欧美日本另类| 日韩图片一区| 亚洲黄色三级| 好看的亚洲午夜视频在线| 国产精品国产馆在线真实露脸| 美日韩在线观看| 久久精品成人一区二区三区| 亚洲图片欧美一区| 日韩小视频在线观看专区| 欧美国产日韩在线| 麻豆精品视频在线观看视频| 久久国产免费| 欧美一级成年大片在线观看| 中文av一区二区| 一区二区三区免费看| 亚洲毛片一区| 亚洲三级视频| 亚洲美女区一区| 亚洲日本国产| 亚洲精品美女在线观看| 在线国产精品一区| 在线播放豆国产99亚洲| 黄色影院成人| 亚洲第一黄色| 1024日韩| 亚洲精品久久嫩草网站秘色| 亚洲国产视频一区| 亚洲日本精品国产第一区| 亚洲全黄一级网站| 亚洲欧洲精品一区| 日韩写真视频在线观看| 一本色道88久久加勒比精品| 亚洲视频精选| 香蕉久久一区二区不卡无毒影院| 亚洲欧美制服另类日韩| 欧美自拍偷拍午夜视频| 久久久久久久久久久一区| 久久综合九色99| 欧美成人69| 亚洲六月丁香色婷婷综合久久| 一区二区三区高清| 亚洲中字在线| 久久久噜噜噜久久中文字幕色伊伊 | 欧美日韩一区在线视频| 欧美午夜不卡视频| 国产欧美日韩视频一区二区| 国产一区清纯| 亚洲靠逼com| 午夜久久99| 美玉足脚交一区二区三区图片| 亚洲第一页在线| 亚洲调教视频在线观看| 久久gogo国模啪啪人体图| 久久久噜噜噜久久中文字幕色伊伊| 欧美v日韩v国产v| 欧美日韩在线视频一区二区| 国产香蕉久久精品综合网| 揄拍成人国产精品视频| 99热这里只有精品8| 先锋影音网一区二区| 99在线视频精品| 亚洲在线一区二区三区| 欧美中文字幕在线观看| 欧美高清免费| 国产日韩欧美精品| 亚洲理伦电影| 久久婷婷国产综合尤物精品 | 欧美一区二区三区在线视频| 六月丁香综合| 中日韩美女免费视频网站在线观看| 久久国产婷婷国产香蕉| 欧美日韩精品免费看| 韩国三级在线一区| 一本久道综合久久精品| 久久一二三四| 亚洲一区高清| 欧美黄色精品| 亚洲成人在线观看视频| 欧美一区二区视频在线| av成人动漫| 欧美第一黄网免费网站| 激情亚洲网站| 欧美中文字幕不卡|