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

            kenlistian

            厚積薄發(fā). 勤為槳,思為帆

               :: 首頁 :: 新隨筆 ::  :: 聚合  :: 管理 ::
              73 隨筆 :: 4 文章 :: 22 評論 :: 0 Trackbacks

                 在網(wǎng)絡(luò)通訊中,由于網(wǎng)絡(luò)擁擠或一次發(fā)送的數(shù)據(jù)量過大等原因,經(jīng)常會發(fā)生交換的數(shù)據(jù)在短時間內(nèi)不能傳送完,收發(fā)數(shù)據(jù)的函數(shù)因此不能返回,這種現(xiàn)象叫做阻塞。 Winsock對有可能阻塞的函數(shù)提供了兩種處理方式:阻塞和非阻塞方式。

            阻塞模式

                 在阻塞方式下,收發(fā)數(shù)據(jù)的函數(shù)在被調(diào)用后一直要到傳送完畢或者出錯才能返回。在阻塞期間,被阻的函數(shù)不會斷調(diào)用系統(tǒng)函數(shù)GetMessage()來保持消息循環(huán)的正常進(jìn)行。

            非阻塞模式
                    將一個套接字置為非阻塞模式之后, Winsock API調(diào)用會立即返回。一般這些調(diào)用都會“失敗”,并返回一個WSAEWOULDBLOCK。表明其操作在調(diào)用期間沒有時間完成。如在系統(tǒng)的輸入緩沖區(qū)中,并不存在等待的數(shù)據(jù),那recv調(diào)用就會返回WSAEWOULDBLOCK錯誤。通常,我們需要重復(fù)調(diào)用同一個函數(shù),直至獲得一個成功返回代碼。這不是一個好的方法。通常采用Winsock的套接字I/O模型去處理。

            套接字I/O模型共有五種類型,如下:

              select(選擇) 
              WSAAsyncSelect(異步選擇)
              WSAEventSelect(事件選擇)
              overlapped(重疊)
              completion port(完成端口)

             

            *WSAAsyncSelect

                  Winsock通過WSAAsyncSelect()自動地設(shè)置套接字處于非阻塞方式。使用WindowsSockets實(shí)現(xiàn)Windows網(wǎng)絡(luò)程序設(shè)計(jì)的關(guān)鍵就是它提供了對網(wǎng)絡(luò)事件基于消息的異步存取,用于注冊應(yīng)用程序感興趣的網(wǎng)絡(luò)事件。它請求Windows Sockets DLL在檢測到套接字上發(fā)生的網(wǎng)絡(luò)事件時,向窗口發(fā)送一個消息。

             int PASCAL FAR WSAAsyncSelect(SOCKET s,HWND hWnd,unsigned int wMsg,long lEvent);
            hWnd:窗口句柄
            wMsg:需要發(fā)送的消息
            lEvent:事件(以下為事件的內(nèi)容)
            值: 含義:
            FD_READ 期望在套接字上收到數(shù)據(jù)(即讀準(zhǔn)備好)時接到通知
            FD_WRITE 期望在套接字上可發(fā)送數(shù)據(jù)(即寫準(zhǔn)備好)時接到通知
            FD_OOB 期望在套接字上有帶外數(shù)據(jù)到達(dá)時接到通知
            FD_ACCEPT 期望在套接字上有外來連接時接到通知
            FD_CONNECT 期望在套接字連接建立完成時接到通知
            FD_CLOSE 期望在套接字關(guān)閉時接到通知

                   進(jìn)行異步選擇使用WSAAsyncSelect()函數(shù)時,有以下幾點(diǎn)需要引起特別的注意:
              .連續(xù)使用兩次WSAAsyncSelect()函數(shù)時,只有第二次設(shè)置的事件有效,如:
                       WSAAsyncSelect(s,hwnd,wMsg1,FD_READ);
                       WSAAsyncSelect(s,hwnd,wMsg2,FD_CLOSE);
                    這樣只有當(dāng)FD_CLOSE事件發(fā)生時才會發(fā)送wMsg2消息。
              .可以在設(shè)置過異步選擇后通過再次調(diào)用WSAAsyncSelect(s,hwnd,0,0);的形式取消在套接字上所設(shè)置的異步事件。
              .Windows Sockets DLL在一個網(wǎng)絡(luò)事件發(fā)生后,通常只會給相應(yīng)的應(yīng)用程序發(fā)送一個消息,而不能發(fā)送多個消息。但通過使用一些函數(shù)隱式地允許重發(fā)此事件的消息,這樣就可能再次接收到相應(yīng)的消息。
              .在調(diào)用過closesocket()函數(shù)關(guān)閉套接字之后不會再發(fā)生FD_CLOSE事件。


                 對UDP協(xié)議,這些網(wǎng)絡(luò)事件主要為:
                  FD_READ   期望在套接字收到數(shù)據(jù)(即讀準(zhǔn)備好)時接收通知;
                  FD_WRITE 期望在套接字可發(fā)送數(shù)(即寫準(zhǔn)備好)時接收通知;
                FD_CLOSE 期望在套接字關(guān)閉時接電通知
              消息變量wParam指示發(fā)生網(wǎng)絡(luò)事件的套接字,變量1Param的低字節(jié)描述發(fā)生的網(wǎng)絡(luò)事件,高字包含錯誤碼。如在窗口函數(shù)的消息循環(huán)中均加一個分支:
            int ok=sizeof(SOCKADDR);
            case wMsg;
            switch(1Param)
            {
                case FD_READ:  //套接字上讀數(shù)據(jù) 
                if(recvfrom(sr.lpPlayData[j],dwDataSize,0,(struct sockaddr FAR*)&there1,
                 (int FAR*)&ok)==SOCKET_ERROR0) {
                            MessageBox(hwnd,“數(shù)據(jù)接收失敗!”,“”,MB_OK);
                            return(FALSE);
                   }
                case FD_WRITE:    //套接字上寫數(shù)據(jù)
              }
            break;

             

             

            *WSAEventSelect
                  事件通知模型要求在程序中針對使用的每個套接字創(chuàng)建一個事件對象,然后通過事件模式通知程序其套接字是否收到或發(fā)送的信息。一般來說這種模式,一般就是通過類似調(diào)用waitformultipleObject一樣在一個線程中等待信號事件來,來了就處理。具體調(diào)用的函數(shù)如下:

                創(chuàng)建WSACreateEvent函數(shù).該函數(shù)的返回值是一個創(chuàng)建好的事件對象句柄。事件對象句柄完后,接下來將其與某個套接字關(guān)聯(lián)在一起,同時注冊自己感興趣的網(wǎng)絡(luò)事件類型,方法是調(diào)用WSAEventSelect函數(shù),對它的定義如下:

               int WSAEventSelect (
                          SOCKET s,                              //需要非阻塞處理的套接字
                          WSAEVENT hEventObject,    //WSACreateEvent 創(chuàng)建來的,關(guān)聯(lián)到socket
                          long lNetworkEvents     
                           );
                lNetworkEvents,對應(yīng)一個“位掩碼”,用于指定應(yīng)用程序感興趣的各種網(wǎng)絡(luò)事件類型的一個組合。要想獲知對這些事件類型的詳細(xì)說明,請參考早先討論過的WSAAsyncSelect I/O模型。
                  為WSAEventSelect創(chuàng)建的事件擁有兩種工作狀態(tài),以及兩種工作模式。
                兩種工作狀態(tài)分別是“已傳信”(signaled)和 “未傳信”(nonsignaled)。
                工作模式則包括“人工”(manual reset)和“自動”(auto reset)。
                  

                  WSACreateEvent缺省時其信號狀態(tài)為0,且為人工設(shè)置,當(dāng)網(wǎng)絡(luò)事件觸發(fā)了與一個套接字關(guān)聯(lián)在一起的事件對象,其事件信號置1。在完成了一個I/O請求的處理之后,需要調(diào)用WSAResetEvent復(fù)位處理(置信號為0)。
                 一個套接字同一個事件對象句柄關(guān)聯(lián)在一起后,應(yīng)用程序便可開始I/O處理;方法是等待網(wǎng)絡(luò)事件觸發(fā)事件對象句柄的工作狀態(tài)。
                 一般而言,在等待網(wǎng)絡(luò)傳來事件時,類似WaitforMultipleObject,其WSAWaitForMultipleEvents函數(shù)的設(shè)計(jì)宗旨便是用來等待一個或多個事件對象句柄,并在事先指定的一個或所有句柄進(jìn)入有信號狀態(tài)后,或在超過了一個規(guī)定的時間周期后,立即返回(線程往往在這里死等)。

               下面是 WSAWaitForMultipleEvents函數(shù)的定義:
            DWORD WSAWaitForMultipleEvents(
              DWORD cEvents,                 
              const WSAEVENT FAR *lphEvents
              BOOL fWaitAll,                 
              DWORD dwTimeOUT,               
              BOOL fAlertable                
            );

            其用法和WaitForMultipleObject類似。
            cEvents和lphEvents參數(shù)定義了由WSAEVENT對象構(gòu)成的一個數(shù)組。在這個數(shù)組中,cEvents指定的是事件對象的數(shù)量,而lphEvents對應(yīng)的是一個指針,用于直接引用該數(shù)組。
                 要注意的是, WSAWaitForMultipleEvents只能支持由WSA_MAXIMUM_WAIT_EVENTS對象規(guī)定的一個最大值,在此定義成64個。故該I/O模型一次最多都只能支持64個套接字。假如想讓這個模型同時管理不止64個套接字,必須創(chuàng)建更多的工作者線程,以便等待更多的事件對象。

            fWaitAl l 參數(shù)指定了WSAWaitForMultiple Events如何等待在事件數(shù)組中的對象。
               =TRUE,那么只有等lphEvents數(shù)組內(nèi)包含的所有事件對象都處于有信號狀態(tài),函數(shù)才會返回;

               =FALSE,任一個事件對象進(jìn)入有信號時,函數(shù)就會返回。

             dwTimeout參數(shù)規(guī)定了 WSAWaitForMultipleEvents最多可等待一個網(wǎng)絡(luò)事件發(fā)生有多長時間。超過規(guī)定的時間,函數(shù)就會立即返回。并返回WSA_WAIT_TIMEOUT。如dwsTimeout設(shè)為WSA_INFIN ITE(永遠(yuǎn)等待),那么根據(jù)fWaiiAll或等待一個網(wǎng)絡(luò)事件或所有網(wǎng)絡(luò)事件都傳信號后,才能從該函數(shù)退出。
             fAlertable,缺省設(shè)為FALSE。主要用于在重疊式I/O模型中.

              當(dāng)設(shè)置fWaiAll=false,WaitForMultipleObject再有網(wǎng)絡(luò)事件時,會返回一個值,指出造成函數(shù)返回的事件對象。根據(jù)WSAWaitForMultipleEvents的返回值,減去預(yù)定義值WSA_WAIT_EVENT_0,得到具體的引用值(即索引位置),程序便可用事件數(shù)組中已發(fā)信號的事件,檢索與那個事件對應(yīng)的套接字,知道了造成網(wǎng)絡(luò)事件的套接字后,調(diào)用 WSAEnumNetworkEvents函數(shù),調(diào)查發(fā)生了什么類型的網(wǎng)絡(luò)事件。該函數(shù)定義如下:
            int WSAEnumNetworkEvents (
              SOCKET s,                                      //檢索該套接字
              WSAEVENT hEventObject,             
              LPWSANETWORKEVENTS lpNetworkEvents 
            );
                hEventObject參數(shù)則是可選的;它指定了一個事件句柄,對應(yīng)于打算重設(shè)的那個事件對象。由于我們的事件對象處在一個有信號狀態(tài),所以可將它傳入,令其自動成為無信號狀態(tài)。
                也可以采用使用 WSAResetEvent 函數(shù)復(fù)位事件信號。
               lpNetworkEvents,就是返回的結(jié)果信息,它是一個指向WSANETWORKEVENTS結(jié)構(gòu)的指針,用于接收套接字上發(fā)生的網(wǎng)絡(luò)事件類型以及可能出現(xiàn)的任何錯誤代碼。

            其WSANETWORKEVENTS結(jié)構(gòu)的定義:
            typedef struct _WSANETWORKEVENTS
            {
                 long lNetworkEvents;
                 int iErrorCode[FD_MAX_EVENTS];
            } WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS;
            lNetworkEvents參數(shù)指定了一個值,對應(yīng)于套接字上發(fā)生的所有網(wǎng)絡(luò)事件類型。
                  注意一個事件進(jìn)入置1(有信號)狀態(tài)時,可能會同時發(fā)生多個網(wǎng)絡(luò)事件類型。如,一個忙的服務(wù)器可能同時收到FD_READ和FD_WRITE通知。 iErrorCode參數(shù)指定的是一個錯誤代碼數(shù)組,同lNetworkEvents中的事件關(guān)聯(lián)在一起。針對每個網(wǎng)絡(luò)事件類型,都存在著一個特殊的事件索引,名字與事件類型的名字類似,只是要在事件名字后面添加一個“ _BIT”后綴字串即可。如,對FD_READ事件類型來說,iErrorCode數(shù)組的索引標(biāo)識符便是FD_READ_BIT。

            posted on 2007-12-27 18:01 kenlistian 閱讀(6643) 評論(1)  編輯 收藏 引用

            評論

            # re: socket異步筆記 2008-09-04 10:21 david.hu
            很不錯.寫的很清楚
            "FD_READ 期望在套接字上收到數(shù)據(jù)(即讀準(zhǔn)備好)時接到通知 "~~

            比msdn 都清楚  回復(fù)  更多評論
              


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            99久久伊人精品综合观看| 久久久91精品国产一区二区三区 | 精品久久777| 精品久久久久久亚洲| 久久国产精品无码网站| 久久久久人妻一区二区三区| 亚洲狠狠婷婷综合久久蜜芽| 久久91综合国产91久久精品| 久久这里有精品| 婷婷综合久久狠狠色99h| 亚洲国产婷婷香蕉久久久久久| 久久不见久久见免费视频7| 99久久国产免费福利| 漂亮人妻被中出中文字幕久久| www.久久99| 久久综合鬼色88久久精品综合自在自线噜噜 | 中文无码久久精品| 精品久久人人妻人人做精品 | 久久精品国产影库免费看| 国内精品伊人久久久影院| 国产AⅤ精品一区二区三区久久| 色综合久久中文字幕无码| 亚洲国产精品一区二区三区久久| 亚洲国产精品久久久久网站| 久久久久亚洲精品天堂| 亚洲精品无码久久一线| 亚洲AV伊人久久青青草原| Xx性欧美肥妇精品久久久久久 | 国内精品久久久久久中文字幕| 婷婷久久香蕉五月综合加勒比| 久久天天躁狠狠躁夜夜不卡| 欧美久久一级内射wwwwww.| 国产99久久久国产精品~~牛| 久久免费高清视频| 久久亚洲精品视频| 伊人久久大香线焦综合四虎 | 人妻无码久久精品| 久久婷婷五月综合色99啪ak | 国产精品久久久久久| 久久99精品久久久久久hb无码| 性高湖久久久久久久久|