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

yehao's Blog

理解完成端口(IO completion port)

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/kevinlynx/archive/2008/01/27/2068739.aspx


  關于完成端口網上有很多文章,不過我個人覺得大多都講得不夠清楚。給的例子要不就是給一個復雜的封裝,要不就是給一個簡單的收發數據。注意,完成端口不僅僅用于網絡數據的收發,它可以用于windows 平臺的各種IO操作。不過我這里只關注在winsock編程中的應用。

    要寫出一篇真的讓人能夠明白的文章,不那么容易。這里我只暫時貼些我的理解。遲些時候如果有空的話,我倒有興趣寫個詳細的入門文章。

1.26.2008

Kevin Lynx

 
理解完成端口:
 
       就目前所了解的信息來說,完成端口通常都會與重疊IO有關聯。完成端口可被看作是一個隊列。各種操作都會被放到該隊列里,程序在遲些時候查詢此隊列獲取之前提交的IO操作結果。

       注意,無論是重疊IO還是完成端口,都不僅僅用于socket的操作,他們是用于各種IO的操作。


IOCP不是為每一個客戶端連接建立一個線程。

要區分IOCP和事件通知模型的區別,事件通知模型是先得到事件,然后根據事件類型去獲取或者發送數據;而IOCP則是先提交動作(發送或接收),后得到通知,當得到通知時,通常就意味著之前提交的動作已經完成了。

 
When you use IOCP, you spawn a pool of threads once - and they are used to handle the network I/O in your application. Technically, in Windows 2000, you don't even have to spawn the pool yourself - you can let Windows take care of the spawning and management of the threads in the pool。

IOCP其實也屬于一種同步對象,就像Windows里的Event對象一樣。IOCP用于同步IO操作。在異步IO操作中,提交了一個異步操作后,某些時候就需要得知操作的結果,也就是同步一下。

 
http://www.codeproject.com/KB/IP/iocp_server_client.aspx
A server application is fairly meaningless if it cannot service multiple clients at the same time, usually asynchronous I/O calls and multithreading is used for this purpose. By definition, an asynchronous I/O call returns immediately, leaving the I/O call pending. At some point of time, the result of the I/O asynchronous call must be synchronized with the main thread. This can be done in different ways. The synchronization can be performed by:
•Using events - A signal is set as soon as the asynchronous call is finished. The disadvantage of this approach is that the thread has to check or wait for the event to be set. •Using the GetOverlappedResult function - This approach has the same disadvantage as the approach above. •Using Asynchronous Procedure Calls (or APC) - There are several disadvantages associated with this approach. First, the APC is always called in the context of the calling thread, and second, in order to be able to execute the APCs, the calling thread has to be suspended in the so called alterable wait state. •Using IOCP - The disadvantage of this approach is that there are many practical thorny programming problems that must be solved. Coding IOCP can be a bit of a hassle. 
這里我要特別強調一下異步IO和非阻塞IO的區別,異步IO就是把IO提交給系統,讓系統替你做,做完了再用某種方式通知你;非阻塞IO就是你要通過某種方式不定時地向系統詢問你是否可以開始做某個IO,當可以開始后,還是要自己來完成IO。
 
       不可以通過接受數據是否為0來判斷客戶端是否斷開,只有當調用closesocket時才可以通過這個方法判斷,如果是意外退出(斷電,網絡故障),則判斷不出。這個時候可以采用定時發送數據(心跳信息)來確認。

 
       創建IOCP程序,一般的步驟:

1.       創建一個單句柄數據結構體,該結構體里一般都包含一個套接字數據。因為IOCP實際上會有固定的幾個線程(工作線程),這些線程在IOCP結果隊列里查詢IO操作結果。這些結果不止是在一個套接字上進行的操作(讀或寫),而是包括了所有與該IOCP對象關聯起來的套接字上的操作結果。因此,為了區分某次操作結果屬于哪個套接字,就需要這個單句柄數據結構里包含這個套接字句柄。

2.       創建一個以OVERLAPPED為首個元素的數據結構體。該結構體實際上對應著一個IO操作(例如WSASend)。對于 WSASend, WSARecv以及查詢操作結果函數都需要一個OVERLAPPED參數(一般是指針),通常情況下我們需要更多的數據,因此定義的這個結構體里通常包含了更多的數據(例如WSABUF,它可以用來容納WSARecv接受到的數據)。之所以要把OVERLAPPED 作為這個結構體的第一個元素,是為了在使用查詢函數GetQueuedCompletionStatus后,可以通過該函數返回的OVERLAPPED類型的指針得到我們這里定義的結構體對象地址,從而獲取更多的數據。

3.       每一次接受到新的連接時(accept),都將這個新的套接字與完成端口相關聯。并且創建一個單句柄對象(也就是完成鍵)。每一個套接字都有一個關聯的單句柄對象。而每一個IO操作都有一個關聯的OVERLAPPED相關的數據結構(上一步定義的結構體)。

4.       可以在任何時候提交異步IO請求,例如WSASend, WSARecv。這里需要為OVERLAPPED相關的結構體指定操作類型。一個典型的結構體為(即第二步定義的結構體):

              struct IOContext
{
              /// 很多函數需要此參數
              OVERLAPPED ol;
              /// 存放接受數據
              char buf[MAX_BUF];
              ///
              WSABUF wsabuf;
              /// 操作類型,提交IO操作時指定該值,在查詢操作結果時,可以重新獲取到該值
              int op_type;
};
在創建該結構體的變量時,為op_type指定一個值。然后將此結構體的地址給WSASend之類的函數。在工作者線程中執行查詢時,實際上得到了該結構體的地址(結構體變量),那么,就可以獲取op_type的值。
注意:查詢結構只能獲取IO操作的字節數(以及IO操作結果數據),不能知道IO操作的類型。所以IO操作的類型實際上是在這里用戶自己指定的。
當執行WSASend時,設置op_type為SEND(自己定義的常量),執行WSARecv時,指定READ。然后在查詢結果時,可以根據op_type知道這個操作結果是什么類型。如果是SEND,那么就表示之前提交的WSASend操作。
IOCP是一個異步操作機制,之所以是異步,就是因為可以隨時提交IO操作。提交之后具體的操作由系統為你完成。完成后就需要某種機制來得知操作結果。IOCP設置的這個結果隊列就是一種機制。
 
      
 
5.       可以通過PostQueuedCompletionStatus手動地往結果隊列里放置一個操作結果。通常這個函數都用于讓工作者線程退出。例如:

                   PostQueuedCompletionStatus( cp_handle, 0, NULL, NULL );
然后在工作者線程里:

         ret = GetQueuedCompletionStatus( cp_handle, &transfer_bytes, (PULONG_PTR) &hc,
              (LPOVERLAPPED*)&ic, INFINITE );
         if( ic == NULL )
         {
              printf( "ic == NULL\n" );
              /*
                   使用PostQueuedCompletionStatus傳遞過來的數據,
                   這里約定ic==NULL時退出
              */
              break;
         }
        
6.     如果不提交任何IO操作,那么結果隊列里很有可能一直都是空的。那么GetQueued這個查詢函數就會一直得不到數據。
 
7.     縱觀IOCP程序,一個比較復雜的地方在于資源的釋放。在接收到一個新的連接時,會為這個連接創建單句柄數據,執行IO操作的話,還要創建OVERLAPPED相關結構體變量。這些變量的地址都會在工作者線程中通過GetQueued..函數獲取,并在工作者線程中使用。一個比較直接的做法是在工作者線程中釋放這些資源。
 
 
 
推薦些文章:

幾種socket模型的代碼:http://blog.csdn.net/mlite/archive/2006/04/30/699340.aspx
                  又一個簡單的IOCP代碼:http://www.go321.cn/html/app/cpp/20070526/30207.html
                  另一個例子,那幅圖有點意義:http://www.3800hk.com/Article/cxsj/vc/wllbcvc/2005-08-25/Article_54111.html
                  codeproject上的文章:http://www.codeproject.com/KB/IP/iocp_server_client.aspx
                  codeproject上的另一篇:http://www.codeproject.com/KB/IP/jbsocketserver1.aspx
                  MSDN上的,前部分由點意義:http://msdn.microsoft.com/msdnmag/issues/1000/winsock/
                
                 其實完成端口的例子在細節上有很多方法,例如accept, AcceptEx之類,對于accept的處理尤其多。這些無疑又給初學者帶來了迷惑。我覺得只要把握住幾個要點就行了:異步操作,結果隊列,數據的傳送(提交操作時傳進去,查詢時取出來),工作者線程

posted on 2011-04-24 18:59 厚積薄發 閱讀(3089) 評論(0)  編輯 收藏 引用 所屬分類: 網絡編程

導航

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

常用鏈接

留言簿

隨筆分類

文章分類

文章檔案

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美日韩国产色视频| 国产精品美女视频网站| 影音先锋一区| 免费亚洲一区二区| 美国成人直播| 一道本一区二区| 一区二区欧美日韩| 国产日韩欧美精品综合| 久久久午夜视频| 欧美成人精品影院| 亚洲尤物精选| 久久精品亚洲一区二区| 亚洲激情啪啪| 亚洲视频精选| 伊人久久成人| 在线亚洲欧美| 激情亚洲网站| 99精品视频免费观看| 国产亚洲综合精品| 亚洲国产综合视频在线观看| 欧美日韩国内| 久久亚洲欧美| 欧美精品色网| 麻豆成人在线观看| 欧美视频日韩| 美乳少妇欧美精品| 欧美性猛交视频| 欧美88av| 国产女主播一区二区三区| 亚洲大片在线| 国产午夜精品久久久久久免费视| 欧美激情导航| 国产欧美一区二区精品忘忧草| 亚洲电影第1页| 国产精品在线看| 亚洲欧洲精品一区二区三区| 国产一区二区按摩在线观看| 亚洲欧洲精品天堂一级| 韩日欧美一区二区| 中日韩午夜理伦电影免费| 亚洲第一福利在线观看| 亚洲在线播放| 一区二区三区四区在线| 久久综合给合久久狠狠色| 久久成人精品一区二区三区| 欧美人交a欧美精品| 久久精品理论片| 国产精品大全| 亚洲免费观看在线视频| 亚洲人成高清| 噜噜噜在线观看免费视频日韩| 欧美一级夜夜爽| 国产精品v日韩精品v欧美精品网站 | 亚洲二区视频| 国内精品视频久久| 午夜精品视频在线观看| 亚洲欧美激情视频| 欧美三级欧美一级| 亚洲毛片网站| 一区二区欧美日韩| 欧美另类高清视频在线| 亚洲欧洲日本在线| 亚洲老板91色精品久久| 欧美凹凸一区二区三区视频| 男女精品网站| 亚洲国产精品精华液网站| 久久在精品线影院精品国产| 麻豆91精品91久久久的内涵| 亚洲成人资源| 美女日韩欧美| 亚洲国产天堂久久国产91| 亚洲精品小视频在线观看| 欧美sm视频| 亚洲日韩中文字幕在线播放| 中文在线资源观看视频网站免费不卡| 欧美黄色日本| 一区二区激情小说| 午夜电影亚洲| 国产专区欧美精品| 麻豆精品91| 亚洲激情视频网| 亚洲一区二区三区中文字幕| 国产精品入口| 久久久精品国产免费观看同学| 欧美1区视频| 一区二区三区欧美成人| 国产精品美女在线观看| 久久精品国产亚洲精品| 欧美激情一区二区三区全黄 | 伊人久久成人| 欧美日本成人| 亚洲欧美日韩成人高清在线一区| 久久久久久网站| 亚洲精品免费观看| 国产精品一区视频| 久久亚洲国产精品一区二区| 亚洲日韩第九十九页| 欧美在线你懂的| 亚洲高清视频的网址| 欧美日韩亚洲高清一区二区| 欧美亚洲综合在线| 91久久精品视频| 欧美一区二区三区在线看 | 国产精品日韩欧美大师| 久久免费视频一区| 一区二区日韩免费看| 老鸭窝91久久精品色噜噜导演| 99国内精品久久| 激情欧美一区二区三区| 欧美亚洲成人精品| 欧美成在线观看| 亚欧美中日韩视频| 日韩一级网站| 欧美好骚综合网| 久久精品国产视频| 亚洲免费小视频| 亚洲全黄一级网站| 黄色成人91| 国产精品视频福利| 欧美精品一区二区三区蜜桃| 久久久久久999| 亚洲自拍三区| 一二三区精品| 91久久香蕉国产日韩欧美9色| 久久网站免费| 久久精品日韩欧美| 亚洲午夜日本在线观看| 亚洲精品国产精品国自产在线 | 国产性色一区二区| 欧美视频一区二区三区四区| 欧美a级一区二区| 久久影院午夜片一区| 久久国产直播| 久久国产精品99精品国产| 亚洲一区二区在线免费观看视频| 亚洲欧洲一区二区在线播放| 欧美激情aⅴ一区二区三区| 欧美aⅴ一区二区三区视频| 久久免费一区| 久久嫩草精品久久久精品一| 欧美在线资源| 久久久99免费视频| 久久精品免视看| 久久久蜜桃精品| 久热精品在线视频| 久热re这里精品视频在线6| 久久婷婷国产综合尤物精品| 久久婷婷国产麻豆91天堂| 久久人人97超碰国产公开结果| 久久欧美中文字幕| 美女脱光内衣内裤视频久久网站| 久久亚洲色图| 欧美高清hd18日本| 亚洲激情网站| 亚洲网址在线| 午夜视频一区二区| 久久久久国产精品www| 蜜臀99久久精品久久久久久软件| 欧美成人r级一区二区三区| 欧美激情一区二区在线| 欧美日韩国产一区二区三区| 国产精品高潮呻吟久久| 国产亚洲一区在线| 亚洲激情专区| 亚洲一区二区三区免费视频| 久久gogo国模啪啪人体图| 久久久久久亚洲精品中文字幕| 美女图片一区二区| 日韩一级免费观看| 性色av香蕉一区二区| 久久夜色撩人精品| 欧美视频在线一区二区三区| 国产精品男gay被猛男狂揉视频| 国产一区二区三区丝袜| 18成人免费观看视频| 亚洲无玛一区| 卡一卡二国产精品| 亚洲靠逼com| 久久国产精品99久久久久久老狼| 欧美777四色影视在线| 国产精品久久久久久久久借妻 | 国产一区二区三区久久 | 蜜桃视频一区| av成人老司机| 久久精品视频在线播放| 欧美日本三区| 伊人成人在线| 午夜欧美大片免费观看 | 亚洲永久视频| 欧美成人中文字幕| 亚洲欧美日韩国产中文| 欧美成人免费小视频| 国产日韩av一区二区| 亚洲最新在线| 欧美成人午夜激情| 欧美一区2区三区4区公司二百| 欧美久久久久久久久| 在线观看av不卡| 久久精品30| 亚洲视频专区在线|