• <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++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              136 隨筆 :: 78 文章 :: 353 評(píng)論 :: 0 Trackbacks
            完成端口中的單句柄數(shù)據(jù)結(jié)構(gòu)與單IO數(shù)據(jù)結(jié)構(gòu)的理解與設(shè)計(jì)

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

              完成端口模型,針對(duì)于WIN平臺(tái)的其它異步網(wǎng)絡(luò)模型而言,最大的好處,除了性能方面的卓越外,還在于完成端口在傳遞網(wǎng)絡(luò)事件的通知時(shí),可以一并傳遞與此事件相關(guān)的應(yīng)用層數(shù)據(jù)。這個(gè)應(yīng)用層數(shù)據(jù),體現(xiàn)在兩個(gè)方面:一是單句柄數(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
                 );
              其中,我們把第三個(gè)參數(shù)lpCompletionKey稱為完成鍵,由它傳遞的數(shù)據(jù)稱為單句柄數(shù)據(jù)。我們把第四個(gè)參數(shù)lpOverlapped稱為重疊結(jié)構(gòu)體,由它傳遞的數(shù)據(jù)稱為單IO數(shù)據(jù)。

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

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

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

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

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

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

              關(guān)于重疊IO的知識(shí),請(qǐng)自行GOOGLE相關(guān)資料。簡(jiǎn)單地說(shuō),OVERLAPPED是應(yīng)用層與核心層交互共享的數(shù)據(jù)單元,如果要執(zhí)行一個(gè)重疊IO操作,必須帶有OVERLAPPED結(jié)構(gòu)。在完成端口中,它允許應(yīng)用層對(duì)OVERLAPPED結(jié)構(gòu)進(jìn)行擴(kuò)展和自定義,允許應(yīng)用層根據(jù)自己的需要在OVERLAPPED的基礎(chǔ)上形成新的擴(kuò)展OVERLAPPED結(jié)構(gòu)。一般地,擴(kuò)展的OVERLAPPED結(jié)構(gòu)中,要求放在第一個(gè)的數(shù)據(jù)成員是原OVERLAPPED結(jié)構(gòu)。我們可以形如以下方式定義自己的擴(kuò)展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操作時(shí),應(yīng)用層會(huì)將擴(kuò)展OVERLAPPED結(jié)構(gòu)的地址傳給核心,核心完成相應(yīng)的操作后,仍然通過(guò)原有的這個(gè)結(jié)構(gòu)傳遞操作結(jié)果,比如“接收”操作完成后,RecvDataBuf里存放便是此次接收下來(lái)的數(shù)據(jù)。

              根據(jù)各自應(yīng)用的不同,不同的完成端口設(shè)計(jì)者可能會(huì)設(shè)計(jì)出不同的PER_HANDLE_DATA
            和PER_IO_DATA,我這里給出的設(shè)計(jì)也只是針對(duì)自己的應(yīng)用場(chǎng)合的,不一定就適合你。但我想,最主要的還是要搞明白PER_HANDLE_DATA和PER_IO_DATA兩種結(jié)構(gòu)體的含義、用途,以及調(diào)用流程。
            posted on 2007-06-02 23:19 譚文政 閱讀(883) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)編程vc++.net
            国产国产成人精品久久| 国产精品久久久久久久久| 久久久网中文字幕| 久久精品免费一区二区| 精品久久亚洲中文无码| 99久久超碰中文字幕伊人| 精品久久久久久无码免费| 亚洲人成无码久久电影网站| 午夜欧美精品久久久久久久 | 久久996热精品xxxx| 久久综合久久性久99毛片| 久久人与动人物a级毛片| 国产福利电影一区二区三区,免费久久久久久久精 | 热re99久久6国产精品免费| 久久亚洲国产中v天仙www| 中文成人无码精品久久久不卡| 国产亚洲精品自在久久| 久久成人小视频| 久久精品成人免费观看97| 蜜臀av性久久久久蜜臀aⅴ麻豆 | 久久亚洲精品成人av无码网站| 国产69精品久久久久9999| 久久精品夜夜夜夜夜久久| 久久人人爽人人爽AV片| 久久香蕉国产线看观看99| 久久久亚洲欧洲日产国码aⅴ| 亚洲精品综合久久| 久久精品国产亚洲av瑜伽| 香蕉久久一区二区不卡无毒影院| 久久无码AV中文出轨人妻| 欧美精品福利视频一区二区三区久久久精品 | 99久久国产热无码精品免费| 伊人久久精品无码二区麻豆| 久久精品综合网| 国产69精品久久久久APP下载| 91超碰碰碰碰久久久久久综合| 久久久久亚洲av无码专区 | 久久久无码精品亚洲日韩蜜臀浪潮| 欧洲国产伦久久久久久久 | 久久精品亚洲日本波多野结衣| 久久SE精品一区二区|