• <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>

            twzheng's cppblog

            『站在風(fēng)口浪尖緊握住鼠標(biāo)旋轉(zhuǎn)!』 http://www.cnblogs.com/twzheng

              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              136 隨筆 :: 78 文章 :: 353 評論 :: 0 Trackbacks
            完成端口中的單句柄數(shù)據(jù)結(jié)構(gòu)與單IO數(shù)據(jù)結(jié)構(gòu)的理解與設(shè)計

            本文作者:sodme
            本文出處:http://blog.csdn.net/sodme
            聲明:本文可以不經(jīng)作者同意任意轉(zhuǎn)載、復(fù)制、傳播,但任何對本文的引用均須保留本文的作者、出處及本行聲明信息!謝謝!

              完成端口模型,針對于WIN平臺的其它異步網(wǎng)絡(luò)模型而言,最大的好處,除了性能方面的卓越外,還在于完成端口在傳遞網(wǎng)絡(luò)事件的通知時,可以一并傳遞與此事件相關(guān)的應(yīng)用層數(shù)據(jù)。這個應(yīng)用層數(shù)據(jù),體現(xiàn)在兩個方面:一是單句柄數(shù)據(jù),二是單IO數(shù)據(jù)。

              GetQueuedCompletionStatus函數(shù)的原型如下:
              WINBASEAPI
              BOOL
              WINAPI
              GetQueuedCompletionStatus(
                  IN  HANDLE CompletionPort,
                  OUT LPDWORD lpNumberOfBytesTransferred,
                  OUT PULONG_PTR lpCompletionKey,
                  OUT LPOVERLAPPED *lpOverlapped,
                  IN  DWORD dwMilliseconds
                 );
              其中,我們把第三個參數(shù)lpCompletionKey稱為完成鍵,由它傳遞的數(shù)據(jù)稱為單句柄數(shù)據(jù)。我們把第四個參數(shù)lpOverlapped稱為重疊結(jié)構(gòu)體,由它傳遞的數(shù)據(jù)稱為單IO數(shù)據(jù)。

              以字面的意思來理解,lpCompletionKey內(nèi)包容的東西應(yīng)該是與各個socket一一對應(yīng)的,而lpOverlapped是與每一次的wsarecv或wsasend操作一一對應(yīng)的。

              在網(wǎng)絡(luò)模型的常見設(shè)計中,當(dāng)一個客戶端連接到服務(wù)器后,服務(wù)器會通過accept或AcceptEx創(chuàng)建一個socket,而應(yīng)用層為了保存與此socket相關(guān)的其它信息(比如:該socket所對應(yīng)的sockaddr_in結(jié)構(gòu)體數(shù)據(jù),該結(jié)構(gòu)體內(nèi)含客戶端IP等信息,以及為便于客戶端的邏輯包整理而準(zhǔn)備的數(shù)據(jù)整理緩沖區(qū)等),往往需要創(chuàng)建一個與該socket一一對應(yīng)的客戶端底層通信對象,這個對象可以負(fù)責(zé)保存僅在網(wǎng)絡(luò)層需要處理的數(shù)據(jù)成員和方法,然后我們需要將此客戶端底層通信對象放入一個類似于list或map的容器中,待到需要使用的時候,使用容器的查找算法根據(jù)socket值找到它所對應(yīng)的對象然后進行我們所需要的操作。

              讓人非常高興的是,完成端口“體貼入微”,它已經(jīng)幫我們在每次的完成事件通知時,稍帶著把該socket所對應(yīng)的底層通信對象的指針?biāo)徒o了我們,這個指針就是lpCompletionKey。也就是說,當(dāng)我們從GetQueuedCompletionStatus函數(shù)取得一個數(shù)據(jù)接收完成的通知,需要將此次收到的數(shù)據(jù)放到該socket所對應(yīng)的通信對象整理緩沖區(qū)內(nèi)對數(shù)據(jù)進行整理時,我們已經(jīng)不需要去執(zhí)行l(wèi)ist或map等的查找算法,而是可以直接定位這個對象了,當(dāng)客戶端連接量很大時,頻繁查表還是很影響效率的。哇哦,太帥了,不是嗎?呵呵。

              基于以上的認(rèn)識,我們的lpCompletionKey對象可以設(shè)計如下:
              typedef struct PER_HANDLE_DATA
              {
                SOCKET socket;             //本結(jié)構(gòu)體對應(yīng)的socket值
                sockaddr_in addr;          //用于存放客戶端IP等信息
                char DataBuf[ 2*MAX_BUFFER_SIZE ];  //整理緩沖區(qū),用于存放每次整理時的數(shù)據(jù)
              }

              PER_HANDLE_DATA與socket的綁定,通過CreateIOCompletionPort完成,將該結(jié)構(gòu)體地址作為該函數(shù)的第三個參數(shù)傳入即可。而PER_HANDLE_DATA結(jié)構(gòu)體中addr成員,是在accept執(zhí)行成功后進行賦值的。DataBuf則可以在每次WSARecv操作完成,需要整理緩沖區(qū)數(shù)據(jù)時使用。

              下面我們再來看看完成端口的收、發(fā)操作中所使用到的重疊結(jié)構(gòu)體OVERLAPPED。

              關(guān)于重疊IO的知識,請自行GOOGLE相關(guān)資料。簡單地說,OVERLAPPED是應(yīng)用層與核心層交互共享的數(shù)據(jù)單元,如果要執(zhí)行一個重疊IO操作,必須帶有OVERLAPPED結(jié)構(gòu)。在完成端口中,它允許應(yīng)用層對OVERLAPPED結(jié)構(gòu)進行擴展和自定義,允許應(yīng)用層根據(jù)自己的需要在OVERLAPPED的基礎(chǔ)上形成新的擴展OVERLAPPED結(jié)構(gòu)。一般地,擴展的OVERLAPPED結(jié)構(gòu)中,要求放在第一個的數(shù)據(jù)成員是原OVERLAPPED結(jié)構(gòu)。我們可以形如以下方式定義自己的擴展OVERLAPPED結(jié)構(gòu):
              typedef struct PER_IO_DATA
              {
                OVERLAPPED ovl;
                WSABUF           buf;
                char                    RecvDataBuf[ MAX_BUFFER_SIZE ];   //接收緩沖區(qū)
                char                    SendDataBuf[ MAX_BUFFER_SIZE ];   //發(fā)送緩沖區(qū)
                OpType              opType;                                                       //操作類型:發(fā)送、接收或關(guān)閉等
              }
              
              在執(zhí)行WSASend和WSARecv操作時,應(yīng)用層會將擴展OVERLAPPED結(jié)構(gòu)的地址傳給核心,核心完成相應(yīng)的操作后,仍然通過原有的這個結(jié)構(gòu)傳遞操作結(jié)果,比如“接收”操作完成后,RecvDataBuf里存放便是此次接收下來的數(shù)據(jù)。

              根據(jù)各自應(yīng)用的不同,不同的完成端口設(shè)計者可能會設(shè)計出不同的PER_HANDLE_DATA
            和PER_IO_DATA,我這里給出的設(shè)計也只是針對自己的應(yīng)用場合的,不一定就適合你。但我想,最主要的還是要搞明白PER_HANDLE_DATA和PER_IO_DATA兩種結(jié)構(gòu)體的含義、用途,以及調(diào)用流程。
            posted on 2007-06-02 23:19 譚文政 閱讀(891) 評論(0)  編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)編程vc++.net
            久久精品国产日本波多野结衣| 国产精品久久亚洲不卡动漫| 99久久国产亚洲高清观看2024| 国产 亚洲 欧美 另类 久久| 色综合久久天天综线观看| 97精品国产97久久久久久免费| 久久国产免费观看精品3| 久久精品无码一区二区日韩AV| 伊人久久无码中文字幕| 日本精品久久久久中文字幕| 久久久久亚洲精品无码网址| 久久久久免费看成人影片| 四虎影视久久久免费| 久久精品国产99国产精偷| 99久久精品免费看国产一区二区三区 | 久久人爽人人爽人人片AV| 久久免费视频6| 久久精品国产WWW456C0M| 国产激情久久久久影院小草 | 久久精品国产亚洲麻豆| 久久国产欧美日韩精品| 久久国产成人午夜aⅴ影院 | 亚洲&#228;v永久无码精品天堂久久 | 99久久精品国产毛片| 99久久人妻无码精品系列| 久久99国产乱子伦精品免费| 久久久久免费看成人影片| 久久精品国产亚洲综合色| 久久精品成人欧美大片| 怡红院日本一道日本久久 | 99久久免费国产精品特黄| 久久婷婷五月综合97色直播| 久久综合久久美利坚合众国| 久久综合成人网| 久久99国产精品久久| 久久久国产一区二区三区| 色妞色综合久久夜夜| 久久午夜综合久久| 久久精品国产精品青草| 中文字幕无码久久久| 91精品国产91久久久久久|