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

            8.2 套接字I/O模型
            共有五種類(lèi)型的套接字I / O模型,可讓W(xué)i n s o c k應(yīng)用程序?qū) / O進(jìn)行管理,它們包括: s e l e c t(選擇)、W S A A s y n c S e l e c t(異步選擇)、W S A E v e n t S e l e c t(事件選擇)、o v e r l a p p e d(重疊)以及completion port(完成端口)
            8.2.1 select模型
            s e l e c t(選擇)模型是Wi n s o c k中最常見(jiàn)的I / O模型。之所以稱(chēng)其為“ s e l e c t模型”,是由于它的“中心思想”便是利用s e l e c t函數(shù),實(shí)現(xiàn)對(duì)I / O的管理!最初設(shè)計(jì)該模型時(shí),主要面向的是某些使用U n i x操作系統(tǒng)的計(jì)算機(jī),它們采用的是B e r k e l e y套接字方案。s e l e c t模型已集成到Winsock 1.1中,它使那些想避免在套接字調(diào)用過(guò)程中被無(wú)辜“鎖定”的應(yīng)用程序,采取一種有序的方式,同時(shí)進(jìn)行對(duì)多個(gè)套接字的管理。由于Winsock 1.1向后兼容于B e r k e l e y套接字實(shí)
            施方案,所以假如有一個(gè)B e r k e l e y套接字應(yīng)用使用了s e l e c t函數(shù),那么從理論角度講,毋需對(duì)其進(jìn)行任何修改,便可正常運(yùn)行。
            利用s e l e c t函數(shù),我們判斷套接字上是否存在數(shù)據(jù),或者能否向一個(gè)套接字寫(xiě)入數(shù)據(jù)。之所以要設(shè)計(jì)這個(gè)函數(shù),唯一的目的便是防止應(yīng)用程序在套接字處于鎖定模式中時(shí),在一次I / O綁定調(diào)用(如s e n d或r e c v)過(guò)程中,被迫進(jìn)入“鎖定”狀態(tài);同時(shí)防止在套接字處于非鎖定模式中時(shí),產(chǎn)生W S A E W O U L D B L O C K錯(cuò)誤。除非滿(mǎn)足事先用參數(shù)規(guī)定的條件,否則s e l e c t函數(shù)會(huì)在進(jìn)行I / O操作時(shí)鎖定。s e l e c t的函數(shù)原型如下:

            int select(
            ??????int nfds,
            ??????fd_set FAR * readfds,
            ??????fd_set FAR * writefds,
            ??????fd_set FAR * exceptfds,
            ??????const struct timeval FAR * timeout
            ?????);
            ?????
            其中,第一個(gè)參數(shù)n f d s會(huì)被忽略。之所以仍然要提供這個(gè)參數(shù),只是為了保持與早期的B e r k e l e y套接字應(yīng)用程序的兼容。大家可注意到三個(gè)f d _ s e t參數(shù):一個(gè)用于檢查可讀性(r e a d f d s),一個(gè)用于檢查可寫(xiě)性(w r i t e f d s),另一個(gè)用于例外數(shù)據(jù)(e x c e p t f d s)。從根本上說(shuō),f d _ s e t數(shù)據(jù)類(lèi)型代表著一系列特定套接字的集合。其中, r e a d f d s集合包括符合下述任何一個(gè)條件的套接字:
            ■ 有數(shù)據(jù)可以讀入。
            ■ 連接已經(jīng)關(guān)閉、重設(shè)或中止。
            ■ 假如已調(diào)用了l i s t e n,而且一個(gè)連接正在建立,那么a c c e p t函數(shù)調(diào)用會(huì)成功。
            w r i t e f d s集合包括符合下述任何一個(gè)條件的套接字:
            ■ 有數(shù)據(jù)可以發(fā)出。
            ■ 如果已完成了對(duì)一個(gè)非鎖定連接調(diào)用的處理,連接就會(huì)成功。
            最后,e x c e p t f d s集合包括符合下述任何一個(gè)條件的套接字:
            ■ 假如已完成了對(duì)一個(gè)非鎖定連接調(diào)用的處理,連接嘗試就會(huì)失敗。
            ■ 有帶外(O u t - o f - b a n d,O O B)數(shù)據(jù)可供讀取。
            例如,假定我們想測(cè)試一個(gè)套接字是否“可讀”,必須將自己的套接字增添到r e a d f d s集合,
            再等待s e l e c t函數(shù)完成。s e l e c t完成之后,必須判斷自己的套接字是否仍為r e a d f d s集合的一部分。若答案是肯定的,便表明該套接字“可讀”,可立即著手從它上面讀取數(shù)據(jù)。在三個(gè)參數(shù)中(r e a d f d s、w r i t e f d s和e x c e p t f d s),任何兩個(gè)都可以是空值( N U L L);但是,至少有一個(gè)不能為空值!在任何不為空的集合中,必須包含至少一個(gè)套接字句柄;否則, s e l e c t函數(shù)便沒(méi)有
            任何東西可以等待。最后一個(gè)參數(shù)t i m e o u t對(duì)應(yīng)的是一個(gè)指針,它指向一個(gè)t i m e v a l結(jié)構(gòu),用于決定s e l e c t最多等待I / O操作完成多久的時(shí)間。如t i m e o u t是一個(gè)空指針,那么s e l e c t調(diào)用會(huì)無(wú)限期地“鎖定”或停頓下去,直到至少有一個(gè)描述符符合指定的條件后結(jié)束。對(duì)t i m e v a l結(jié)構(gòu)的
            定義如下:
            struct timeval
            {
            ?long tv_sec;
            ?long tv_usec;
            };

            其中,t v _ s e c字段以秒為單位指定等待時(shí)間; t v _ u s e c字段則以毫秒為單位指定等待時(shí)間。
            若將超時(shí)值設(shè)置為( 0 , 0),表明s e l e c t會(huì)立即返回,允許應(yīng)用程序?qū) e l e c t操作進(jìn)行“輪詢(xún)”。
            出于對(duì)性能方面的考慮,應(yīng)避免這樣的設(shè)置。s e l e c t成功完成后,會(huì)在f d _ s e t結(jié)構(gòu)中,返回剛好有未完成的I / O操作的所有套接字句柄的總量。若超過(guò)t i m e v a l設(shè)定的時(shí)間,便會(huì)返回0。不管由于什么原因,假如s e l e c t調(diào)用失敗,都會(huì)返回S O C K E T _ E R R O R。
            用s e l e c t對(duì)套接字進(jìn)行監(jiān)視之前,在自己的應(yīng)用程序中,必須將套接字句柄分配給一個(gè)集合,設(shè)置好一個(gè)或全部讀、寫(xiě)以及例外f d _ s e t結(jié)構(gòu)。將一個(gè)套接字分配給任何一個(gè)集合后,再來(lái)調(diào)用s e l e c t,便可知道一個(gè)套接字上是否正在發(fā)生上述的I / O活動(dòng)。Wi n s o c k提供了下列宏操作,可用來(lái)針對(duì)I / O活動(dòng),對(duì)f d _ s e t進(jìn)行處理與檢查:
            ■ FD_CLR(s, *set):從s e t中刪除套接字s。
            ■ FD_ISSET(s, *set):檢查s是否s e t集合的一名成員;如答案是肯定的是,則返回T R U E。
            ■ FD_SET(s, *set):將套接字s加入集合s e t。
            ■ F D _ Z E R O ( * s e t ):將s e t初始化成空集合。

            例如,假定我們想知道是否可從一個(gè)套接字中安全地讀取數(shù)據(jù),同時(shí)不會(huì)陷于無(wú)休止的
            “鎖定”狀態(tài),便可使用F D _ S E T宏,將自己的套接字分配給f d _ r e a d集合,再來(lái)調(diào)用s e l e c t。要想檢測(cè)自己的套接字是否仍屬f d _ r e a d集合的一部分,可使用F D _ I S S E T宏。采用下述步驟,便可完成用s e l e c t操作一個(gè)或多個(gè)套接字句柄的全過(guò)程:
            1) 使用F D _ Z E R O宏,初始化自己感興趣的每一個(gè)f d _ s e t。
            2) 使用F D _ S E T宏,將套接字句柄分配給自己感興趣的每個(gè)f d _ s e t。
            3) 調(diào)用s e l e c t函數(shù),然后等待在指定的f d _ s e t集合中,I / O活動(dòng)設(shè)置好一個(gè)或多個(gè)套接字句柄。
            s e l e c t完成后,會(huì)返回在所有f d _ s e t集合中設(shè)置的套接字句柄總數(shù),并對(duì)每個(gè)集合進(jìn)行相應(yīng)的更新。
            4) 根據(jù)s e l e c t的返回值,我們的應(yīng)用程序便可判斷出哪些套接字存在著尚未完成(待決)的I / O操作—具體的方法是使用F D _ I S S E T宏,對(duì)每個(gè)f d _ s e t集合進(jìn)行檢查。
            5) 知道了每個(gè)集合中“待決”的I / O操作之后,對(duì)I / O進(jìn)行處理,然后返回步驟1 ),繼續(xù)進(jìn)行s e l e c t處理。
            s e l e c t返回后,它會(huì)修改每個(gè)f d _ s e t結(jié)構(gòu),刪除那些不存在待決I / O操作的套接字句柄。這正是我們?cè)谏鲜龅牟襟E( 4 )中,為何要使用F D _ I S S E T宏來(lái)判斷一個(gè)特定的套接字是否仍在集合中的原因。在程序清單8 - 4中,我們向大家闡述了為一個(gè)(只有一個(gè))套接字設(shè)置s e l e c t模型所需的一系列基本步驟。若想在這個(gè)應(yīng)用程序中添加更多的套接字,只需為額外的套接字維護(hù)它們的一個(gè)列表,或維護(hù)它們的一個(gè)數(shù)組即可。

            程序清單8-4 用s e l e c t管理一個(gè)套接字上的I / O操作

            SOCKET s;
            fd_set fdread;
            int ret;
            //create a socket ,and accept a connection
            ...
            //manage i/o on the socket

            while(TRUE)
            {
            ?//aways clear the read set before calling
            ?//select()
            ?FD_ZERO(&fdread);
            ?//add socket s to the read set
            ?FD_SET(s,&fdread);
            ?if((ret = select(0,&fdread,NULL,NULL,NULL))== SOCKET_ERROR)
            ?{
            ??//ERROR CONDITION
            ?}
            ?if(ret > 0)
            ?
            ?{
            ??//for this simple case,select() should return the value 1.
            ??//an appliation dealing with more than one socket could get a value greater than 1;
            ??//at this point,your appliation should check to see whether the socket is part of a set.
            ??if(FD_ISSET(s.&fdread))
            ??{
            ???//a read event has occurred on a socket s
            ??}
            ?}

            }
            ??????

            Posted on 2006-09-12 14:41 艾凡赫 閱讀(639) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): 網(wǎng)絡(luò)編程
            久久久久久亚洲精品成人| 99热精品久久只有精品| 久久精品aⅴ无码中文字字幕重口| 色综合久久无码中文字幕| 香蕉久久夜色精品国产小说| 亚洲国产成人久久综合一区77| 无码超乳爆乳中文字幕久久| 狠狠人妻久久久久久综合| 亚洲国产天堂久久综合| 久久免费线看线看| 久久精品国产清自在天天线| 国产成人香蕉久久久久 | 久久久91人妻无码精品蜜桃HD| 国产精品99久久久精品无码| 韩国三级中文字幕hd久久精品| 久久久久人妻精品一区| 久久亚洲精品国产亚洲老地址| 亚洲国产精品久久久久| 国内精品久久久人妻中文字幕| 久久久久99这里有精品10| 久久99精品久久久久久野外| 久久青青草原精品国产| 狠狠色婷婷久久一区二区| 日本精品一区二区久久久| 国产女人aaa级久久久级| 国内精品久久久久| 激情伊人五月天久久综合| 伊人久久大香线焦AV综合影院| 久久免费视频一区| 久久午夜综合久久| 久久99精品久久久久久秒播| 国产福利电影一区二区三区久久久久成人精品综合 | 久久综合色区| 免费精品久久久久久中文字幕| 久久91精品综合国产首页| 国产99久久久久久免费看| 久久99精品国产一区二区三区| 久久99国产精品一区二区| 日本久久久久久中文字幕| 国产A级毛片久久久精品毛片| 久久激情五月丁香伊人|