• <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>
            隨筆-250  評論-20  文章-55  trackbacks-0
            摘自《Visual C++網(wǎng)絡(luò)游戲建模與實現(xiàn)》(蘇羽、王媛媛編著) 
            Win32重疊I/O(Overloapped I/O)機制允許發(fā)起一個操作,然后在操作完成之后接受
            到信息。對于那種需要很長時間才能完成的操作來說,重疊I/O機制尤其有用,因為發(fā)起
            重疊操作的線程在重疊請求發(fā)出后就可以自由地做別的事情了。
                在Windows NT/2000上,提供真正可擴展的I/O模型就是使用完成端口(Completion
            Port)的重疊I/O。
                ……
                可以把完成端口看成系統(tǒng)維護的一個隊列,操作系統(tǒng)把重疊I/O操作完成的事件通知
            放到該隊列里,由于是暴露“操作完成”的事件通知,所以命名為“完成端口”(Completion
            Ports)。一個Socket被創(chuàng)建后,可以在任何時刻和一個完成端口聯(lián)系起來。
                一般來說,一個應(yīng)用程序可以創(chuàng)建多個工作線程來處理完成端口上的通知事件。工作
            線程的數(shù)量依賴于程序的具體需要。但是在理想的情況下,應(yīng)該對應(yīng)一個CPU創(chuàng)建一個線
            程。因為在完成端口理想模型中,每個線程都可以從系統(tǒng)獲得一個“原子”性的時間片,輪
            番運行并檢查完成端口,線程的切換是額外的開銷。在實際開發(fā)的時候,還要考慮這些線
            程是否牽涉到其他堵塞操作的情況。如果某線程進行堵塞操作,系統(tǒng)則將其掛起,讓別的
            線程獲得運行時間。因此,如果有這樣的情況,可以多創(chuàng)建幾個線程來盡量利用時間。
                應(yīng)用完成端口分兩步走:
                1. 創(chuàng)建完成端口句柄:
                HANDLE hIocp;
                hIocp=CreateIoCompletionPort(
                INVALID_HANDLE_VALUE,
                NULL,
                (ULONG_PTR)0,
                0);
                if(hIocp==NULL) {
                //如果錯誤
                  ……
                }
                注意在第1個參數(shù)(FileHandle)傳入INVALID_FILE_HANDLE,第2個參數(shù)(ExistingCompletionPort)
            傳入NULL,系統(tǒng)將創(chuàng)建一個新的完成端口句柄,沒有任何I/O句柄與其關(guān)聯(lián)。

                2. 完成端口創(chuàng)建成功后,在Socket和完成端口之間建立關(guān)聯(lián)。再次調(diào)用CreateIoCompletionPort
            函數(shù),這一次在第1個參數(shù)FileHandle傳入創(chuàng)建的Socket句柄,參數(shù)ExistingCompletionPort
            為已經(jīng)創(chuàng)建的完成端口句柄。
                以下代碼創(chuàng)建了一個Socket并把它和完成端口聯(lián)系起來。
                SOCKET s;
                s=Socket(AF_INET,SOCK_STREAM,0);
                if(s==INVALID_SOCKET) {
                if(CreateIoCompletionPort((HANDLE)s,
                hIocp,
                (ULONG_PTR)0,
                0)==NULL)
                {
                //如果創(chuàng)建失敗
                  ……
                }
                }
                到此為止,Socket已經(jīng)成功和完成端口相關(guān)聯(lián)。在此Socket進行的重疊I/O操作結(jié)果均
            使用完成端口發(fā)出通知。

                注意:CreateIoCompletionPort函數(shù)的第3個參數(shù)允許開發(fā)人員傳入一個類型為ULONG_PTR
            的數(shù)據(jù)成員,我們把它稱為完成鍵(Completion Key),此數(shù)據(jù)成員可以設(shè)計為指向包含Socket
            信息的一個結(jié)構(gòu)體的一個指針,用來把相關(guān)的環(huán)境信息和Socket聯(lián)系起來,每次完成通知來
            到的同時,該環(huán)境信息也隨著通知一起返回給開發(fā)人員。

                完成端口創(chuàng)建以及與Socket關(guān)聯(lián)之后,就要創(chuàng)建一個或多個工作線程來處理完成通知,
            每個線程都可以循環(huán)地調(diào)用GetQueuedCompletionStatus函數(shù),檢查完成端口上的通知事件。
                在舉例說明一個典型的工作線程之前,我們先討論一下重疊I/O的過程。到一個重疊I/O
            被發(fā)起,一個Overlapped結(jié)構(gòu)體的指針就要作為參數(shù)傳遞給系統(tǒng)。當操作完成時,
            GetQueueCompletionStatus就可以返回指向同一個Overlapped結(jié)構(gòu)的指針。為了辨認和定位
            這個已完成的操作,開發(fā)人員最好定義自己的OVERLAPPED結(jié)構(gòu),以包含一些自己定義的關(guān)于
            操作本身的額外信息。比如:
                typedef struct _OVERLAPPELUS {
                  OVERLAPPED ol;
                  SOCKET s, sclient;
                  int OpCode;
                  WSABUF wbuf;
                  DWORD dwBytes, dwFlags;
                } OVERLAPPELUS;
                此結(jié)構(gòu)的第1個成員為默認的OVERLAPPED結(jié)構(gòu),第2和第3個為本地服務(wù)Socket和與該
            操作相關(guān)的客戶socket,第4個成員為操作類型,對于Socket,現(xiàn)在定義的有以下3種:
                #define OP_READ 0
                #define OP_WRITE 1
                #define OP_ACCEPT 2
                然后還有應(yīng)用程序的Socket緩沖區(qū),操作數(shù)據(jù)量,標志位以及其他開發(fā)人員認為有用
            的信息。
                當進行重疊I/O操作,把OVERLAPPELUS結(jié)構(gòu)作為重疊I/O的參數(shù)lpOverlapp傳遞(如
            WSASend,WASRecv,等函數(shù)的lpOverlapped參數(shù),要求傳入一個OVERLAPP結(jié)構(gòu)的指針)。
                當操作完成后,GetQueuedCompletionStatus函數(shù)返回一個LPOVERLAPPED類型的指針,
            這個指針其實是指向開發(fā)人員定義的擴展OVERLAPPELUS結(jié)構(gòu),包含著開發(fā)人員早先傳入的
            全部信息。

                注意:OVERLAPPED成員不一定要求是OVERLAPPELUS擴展結(jié)構(gòu)的一個成員,在獲得
            OVERLAPPED指針之后,可以用CONTAINING_RECORD宏獲得相應(yīng)的擴展結(jié)構(gòu)的指針。

                典型的Worker Thread結(jié)構(gòu):
                DWORD WINAPI WorkerThread(LPVOID lpParam)
                {
                  ULONG_PTR *PerHandleKey;
                  OVERLAPPED *Overlap;
                  OVERLAPPELUS *OverlapPlus, *newolp;
                  DWORD dwBytesXfered;
                 
                  while(1)
                  {
                    ret=GetQueuedCompletionStatus(
                    hIocp,
                    &dwBytesXfered,
                    (PULONG_PTR)&PerHandleKey,
                    &Overlap,
                    INFINITE);
                    if(ret==0)
                    {
                      //如果操作失敗
                      continue;
                    }
                   
                    OverlapPlus=CONTATING_RECORD(Overlap, OVERLAPPELUS, ol);
                    switch(OverlapPlus->OpCode)
                    {
                      case OP_ACCEPT:
                        CreateIoCompletionPort(
                            (HANDLE)OverlapPlus->sclient,
                            hIocp,
                            (ULONG_PTR)0,
                            0);
                        newolp=AllocateOverlappelus();
                        newolp->s=OverlapPlus->sclient;
                        newolp->OpCode=OP_READ;
                        PrepareSendBuffer(&newolp->wbuf);
                        ret=WSASend(
                          newolp->s,
                          &newolp->wbuf,
                          1,
                          &newolp->dwBytes,
                          0,
                          &newolp.ol,
                          NULL);
                        if(ret==SOCKET_ERROR)
                        {
                          if(WSAGetLastError()!=WSA_IO_PENDING)
                          {
                            //進行錯誤處理
                            ……
                          }
                        }
                        FreeOverlappelus(OverlapPlus);
                        SetEvent(hAcceptThread);
                        break;
                      case OP_READ:
                        memset(&OverlapPlus->ol,0,sizeof(OVERLAPPED));
                        ret=WSARecv(
                            OverlapPlus->s,
                            &OverlapPlus->wbuf,
                            1,
                            &OverlapPlus->dwBytes,
                            &OverlapPlus->dwFlags,
                            &OverlapPlus->ol,
                            NULL);
                        if(ret==SOCKET_ERROR)
                        {
                          if(WSAGetLastError()!=WSA_IO_PENDING)
                          {
                            //錯誤處理
                            ……
                          }
                        }
                        break;
                      case OP_WRITE:
                        break;
                    }/*switch結(jié)束*/
                  }/*while結(jié)束*/
                }/*WorkerThread結(jié)束*/
               
                注意:如果Overlapped操作立刻失敗(比如,返回SOCKET_ERROR或其他非
                WSA_IO_PENDING的錯誤),則沒有任何完成通知事件會被放到完成端口隊列里。反之,
                則一定有相應(yīng)的通知事件被放到端口隊列。

            posted on 2007-04-28 17:14 jay 閱讀(679) 評論(0)  編輯 收藏 引用 所屬分類: socket
            久久精品国产免费一区| 97久久国产露脸精品国产| 久久r热这里有精品视频| 国产精品九九久久免费视频| 亚洲国产成人久久综合野外| 国产∨亚洲V天堂无码久久久| 久久国产精品二国产精品| 久久久久久毛片免费播放| 久久精品国产精品亚洲人人 | 国产精品欧美久久久久无广告 | 2021最新久久久视精品爱| 久久91亚洲人成电影网站| 18禁黄久久久AAA片| 色噜噜狠狠先锋影音久久| 久久久久女人精品毛片| 亚洲国产日韩欧美久久| 精品久久久久中文字| 久久婷婷激情综合色综合俺也去| 久久精品国产亚洲精品| 亚洲国产天堂久久综合网站| 婷婷久久久亚洲欧洲日产国码AV| 久久免费视频6| 欧美激情精品久久久久久久| 91久久精品国产91性色也| 久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口 | 久久精品aⅴ无码中文字字幕重口 久久精品a亚洲国产v高清不卡 | 久久国语露脸国产精品电影| 久久久久无码精品| 国内精品久久久久久麻豆| 国内精品久久久久久99蜜桃| 久久水蜜桃亚洲av无码精品麻豆| 四虎国产精品成人免费久久| 久久综合色老色| 久久成人小视频| 国产精品乱码久久久久久软件| 三级片免费观看久久| 狠狠色丁香久久婷婷综合_中| 伊人久久大香线蕉AV色婷婷色| 久久综合久久美利坚合众国| 亚洲精品国精品久久99热一| 国产69精品久久久久久人妻精品|