• <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>
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統(tǒng)計

            • 隨筆 - 21
            • 文章 - 0
            • 評論 - 2
            • 引用 - 0

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            手把手教你玩轉(zhuǎn)網(wǎng)絡(luò)編程模型之完成例程(Completion Routine)篇

            手把手教你玩轉(zhuǎn)網(wǎng)絡(luò)編程模型之完成例程(Completion Routine)

                               ----- By PiggyXP(小豬)

             

              

              記得寫這個系列的上一篇文章的時候已經(jīng)是四年前了,準(zhǔn)確的說是四年半以前了,翻開我塵封已久的blog,感覺到上面已經(jīng)落了厚厚的一層塵土,突然又來了感覺,于是我翻箱倒柜的找出以前的資料,上傳到了我的空間里,而且,順便又為在網(wǎng)絡(luò)編程苦海中苦苦尋覓的朋友帶來一份禮物,這次為大家?guī)淼氖侵丿BIO模型里面的“完成例程”的實(shí)現(xiàn)方式及示例代碼。

            本文凝聚著筆者心血,如要轉(zhuǎn)載,請指明原作者及出處,謝謝!不過代碼寫得不好,歡迎改進(jìn),而且沒有版權(quán),請隨便散播、使用。^_^

            OK, Let’s go !  Have fun!

             

            本文配套的示例源碼下載地址(在我的下載空間里)

            http://download.csdn.net/user/PiggyXP

             (VC++ 2008編寫的多客戶端MFC代碼,配有非常非常詳盡的注釋,功能只是簡單的顯示一下各個客戶端發(fā)來的字符,作為教學(xué)代碼,為了使得代碼結(jié)構(gòu)清晰明了,簡化了很多地方,用于產(chǎn)品開發(fā)的話還需要做很多改進(jìn),有錯誤或者不足的地方,非常歡迎大家不吝指出。)

            代碼界面示意圖:

            完成例程模型示例

            本文假設(shè)你已經(jīng)對重疊I/O的機(jī)制已有了解,否則請先參考本系列的前一篇《手把手教你玩轉(zhuǎn)重疊IO模型》

             

            目錄:

            1 完成例程的優(yōu)點(diǎn)

            2 完成例程的基本原理

            3 關(guān)于完成例程的函數(shù)介紹

            4 完成例程的實(shí)現(xiàn)步驟

            5 實(shí)際應(yīng)用中應(yīng)該進(jìn)一步完善的地方

             

             

            一.         完成例程的優(yōu)點(diǎn)

            1.    首先需要指明的是,這里的“完成例程”(Completion Routine)并非是大家所常聽到的 “完成端口”(Completion Port),而是另外一種管理重疊I/O請求的方式,而至于什么是重疊I/O,簡單來講就是Windows系統(tǒng)內(nèi)部管理I/O的一種方式,核心就是調(diào)用的ReadFileWriteFile函數(shù),在制定設(shè)備上執(zhí)行I/O操作,不光是可用于網(wǎng)絡(luò)通信,也可以用于其他需要的地方。

            Windows系統(tǒng)中,管理重疊I/O可以有三種方式:

            (1)  上一篇中提到的基于事件通知的重疊I/O模型

             (2)  本篇中將要講述的基于“完成例程”的重疊I/O模型

             (3)  下一篇中將要講到的“完成端口”模型

            雖然都是基于重疊I/O,但是因?yàn)榍皟煞N模型都是需要自己來管理任務(wù)的分派 ,所以性能上沒有區(qū)別,而完成端口是創(chuàng)建完成端口對象使操作系統(tǒng)親自來管理任務(wù)的分派,所以完成端口肯定是能獲得最好的性能。

            2.    如果你想要使用重疊I/O機(jī)制帶來的高性能模型,又懊惱于基于事件通知的重疊模型要收到64個等待事件的限制,還有點(diǎn)畏懼完成端口稍顯復(fù)雜的初始化過程,那么“完成例程”無疑是你最好的選擇!^_^ 因?yàn)橥瓿衫虜[脫了事件通知的限制,可以連入任意數(shù)量客戶端而不用另開線程,也就是說只用很簡單的一些代碼就可以利用Windows內(nèi)部的I/O機(jī)制來獲得網(wǎng)絡(luò)服務(wù)器的高性能,是不是心動了呢?那就一起往下看。。。。。。。。。。

            3.    而且個人感覺“完成例程”的方式比重疊I/O更好理解,因?yàn)榫秃臀覀儌鹘y(tǒng)的“回調(diào)函數(shù)”是一樣的,也更容易使用一些,推薦!

             

            二.         完成例程的基本原理

            概括一點(diǎn)說,上一篇拙作中提到的那個基于事件通知的重疊I/O模型,在你投遞了一個請求以后(比如WSARecv),系統(tǒng)在完成以后是用事件來通知你的,而在完成例程中,系統(tǒng)在網(wǎng)絡(luò)操作完成以后會自動調(diào)用你提供的回調(diào)函數(shù),區(qū)別僅此而已,是不是很簡單呢?

            首先這里統(tǒng)一幾個名詞,包括“重疊操作”、“重疊請求”、“投遞請求”等等,這是為了配合這的重疊I/O才這么講的,說的直白一些,也就是你在代碼中發(fā)出的WSARecv()WSASend()等等網(wǎng)絡(luò)函數(shù)調(diào)用。

             上篇文章中偷懶沒畫圖,這次還是畫個流程圖來說明吧,采用完成例程的服務(wù)器端,通信流程簡單的來講是這樣的:

             完成例程流程圖

             

            從圖中可以看到,服務(wù)器端存在一個明顯的異步過程,也就是說我們把客戶端連入的SOCKET與一個重疊結(jié)構(gòu)綁定之后,便可以將通訊過程全權(quán)交給系統(tǒng)內(nèi)部自己去幫我們調(diào)度處理了,我們在主線程中就可以去做其他的事情,邊等候系統(tǒng)完成的通知就OK,這也就是完成例程高性能的原因所在。

            如果還沒有看明白,我們打個通俗易懂的比方,完成例程的處理過程,也就像我們告訴系統(tǒng),說“我想要在網(wǎng)絡(luò)上接收網(wǎng)絡(luò)數(shù)據(jù),你去幫我辦一下”(投遞WSARecv操作),“不過我并不知道網(wǎng)絡(luò)數(shù)據(jù)合適到達(dá),總之在接收到網(wǎng)絡(luò)數(shù)據(jù)之后,你直接就調(diào)用我給你的這個函數(shù)(比如_CompletionProess),把他們保存到內(nèi)存中或是顯示到界面中等等,全權(quán)交給你處理了”,于是乎,系統(tǒng)在接收到網(wǎng)絡(luò)數(shù)據(jù)之后,一方面系統(tǒng)會給我們一個通知,另外同時系統(tǒng)也會自動調(diào)用我們事先準(zhǔn)備好的回調(diào)函數(shù),就不需要我們自己操心了。

            看到這里,各位應(yīng)該已經(jīng)對完成例程的體系結(jié)構(gòu)有了比價清晰的了解了吧,下面各位喝點(diǎn)咖啡轉(zhuǎn)轉(zhuǎn)脖子休息休息,然后就進(jìn)入到下面的具體實(shí)現(xiàn)部分了。

             

            一.         完成例程的函數(shù)介紹

            這個部分將要介紹在完成例程模型中會使用到的關(guān)鍵函數(shù),內(nèi)容比較枯燥,大家要做好心理準(zhǔn)備。不過在實(shí)際應(yīng)用以前,很多東西肯定也不會理解得太深刻,可以先泛泛的了解一下,以后再回頭復(fù)習(xí)這里的知識就可以了。

            厄。。。。。。仔細(xì)審查了一下代碼,發(fā)現(xiàn)其實(shí)這里也沒有什么新函數(shù)好介紹了,大部分都是使用重疊模型那一章里介紹的一樣的函數(shù),需要查看的朋友請看這里《手把手教你玩轉(zhuǎn)重疊IO模型》

            ,這里就不再重復(fù)了:

            這里只補(bǔ)充一個知識點(diǎn),就是咱們完成例程方式和前面的事件通知方式最大的不同之處就在于,我們需要提供一個回調(diào)函數(shù)供系統(tǒng)收到網(wǎng)絡(luò)數(shù)據(jù)后自動調(diào)用,回調(diào)函數(shù)的參數(shù)定義應(yīng)該遵照如下的函數(shù)原型:

             

            1.  完成例程回調(diào)函數(shù)原型及傳遞方式

            函數(shù)應(yīng)該是這樣定義的,函數(shù)名字隨便起,但是參數(shù)類型不能錯

             

            view plaincopy to clipboardprint?

            1. Void CALLBACK _CompletionRoutineFunc(  
            2.   DWORD dwError, // 標(biāo)志咱們投遞的重疊操作,比如WSARecv,完成的狀態(tài)是什么  
            3.   DWORD cbTransferred, // 指明了在重疊操作期間,實(shí)際傳輸?shù)淖止?jié)量是多大  
            4.   LPWSAOVERLAPPED lpOverlapped, // 參數(shù)指明傳遞到最初的IO調(diào)用內(nèi)的一個重疊  結(jié)構(gòu)  
            5.   DWORD dwFlags  // 返回操作結(jié)束時可能用的標(biāo)志(一般沒用));  

                  

            還有一點(diǎn)需要重點(diǎn)提一下的是,因?yàn)槲覀冃枰o系統(tǒng)提供一個如上面定義的那樣的回調(diào)函數(shù),以便系統(tǒng)在完成了網(wǎng)絡(luò)操作后自動調(diào)用,這里就需要提一下究竟是如何把這個函數(shù)與系統(tǒng)內(nèi)部綁定的呢?如下所示,在WSARecv函數(shù)中是這樣綁定的

            view plaincopy to clipboardprint?

            1.        int WSARecv(  

            2.                    SOCKET s,                      // 當(dāng)然是投遞這個操作的套接字  

            3.                    LPWSABUF lpBuffers,          // 接收緩沖區(qū),與Recv函數(shù)不同  

            4.        // 這里需要一個由WSABUF結(jié)構(gòu)構(gòu)成的數(shù)組  

            5.         DWORD dwBufferCount,        // 數(shù)組中WSABUF結(jié)構(gòu)的數(shù)量,設(shè)置為1即可  

            6.           LPDWORD lpNumberOfBytesRecvd,  // 如果接收操作立即完成,這里會返回函數(shù)調(diào)用  

            7.        // 所接收到的字節(jié)數(shù)  

            8.          LPDWORD lpFlags,             // 說來話長了,我們這里設(shè)置為即可  

            9.          LPWSAOVERLAPPED lpOverlapped,  // “綁定”的重疊結(jié)構(gòu)  

            10.       LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine  

            11.                                       // 我們的完成例程函數(shù)的指針  

            12.     );  

            其他參數(shù)我們可以先不用先細(xì)看,只看最后一個,看到了嗎?直接在WSARecv的最后一個參數(shù)上,傳遞一下我們回調(diào)函數(shù)的指針就行了,這里注意一下,咱們這次多次提到的這個“完成例程”,其實(shí)就是指的咱們提供的這個回調(diào)函數(shù)。

             

                 

            view plaincopy to clipboardprint?

            1.    舉個例子:(變量的定義順序和上面的說明的順序是對應(yīng)的,下同)  

            2.    SOCKET s;  

            3.    WSABUF DataBuf;           // 定義WSABUF結(jié)構(gòu)的緩沖區(qū)  

            4.    // 初始化一下DataBuf  

            5.    #define DATA_BUFSIZE 4096  

            6.    char buffer[DATA_BUFSIZE];  

            7.    ZeroMemory(buffer, DATA_BUFSIZE);  

            8.    DataBuf.len = DATA_BUFSIZE;  

            9.    DataBuf.buf = buffer;  

            10.  DWORD dwBufferCount = 1, dwRecvBytes = 0, Flags = 0;  

            11.  // 建立需要的重疊結(jié)構(gòu),每個連入的SOCKET上的每一個重疊操作都得綁定一個  

            12.  WSAOVERLAPPED AcceptOverlapped ;// 如果要處理多個操作,這里當(dāng)然需要一個  

            13.  // WSAOVERLAPPED數(shù)組  

            14.  ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));  

            15.    

            16.  // 作了這么多工作,終于可以使用WSARecv來把我們的完成例程函數(shù)綁定上了  

            17.  // 當(dāng)然,假設(shè)我們的_CompletionRoutine函數(shù)已經(jīng)定義好了  

            18.  WSARecv(s, &DataBuf, dwBufferCount, &dwRecvBytes,   

            19.  &Flags, &AcceptOverlapped, _CompletionRoutine);  

            其他的函數(shù)我這里就不一一介紹了,因?yàn)槲覀儺吘惯€有MSDN這么個好幫手,而且在講后面的完成例程和完成端口的時候我還會講到一些 ^_^

            四.         完成例程的實(shí)現(xiàn)步驟

            基礎(chǔ)知識方面需要知道的就是這么多,下面我們配合代碼,來一步步的講解如何親手實(shí)現(xiàn)一個完成例程模型(前面幾步的步驟和基于事件通知的重疊I/O方法是一樣的)。

            【第一步】創(chuàng)建一個套接字,開始在指定的端口上監(jiān)聽連接請求

            和其他的SOCKET初始化全無二致,直接照搬即可,在此也不多費(fèi)唇舌了,需要注意的是為了一目了然,我去掉了錯誤處理,平常可不要這樣啊,盡管這里出錯的幾率比較小。

            view plaincopy to clipboardprint?

            1.    WSADATA wsaData;  

            2.    WSAStartup(MAKEWORD(2,2),&wsaData);  

            3.      

            4.    ListenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  //創(chuàng)建TCP套接字  

            5.      

            6.    SOCKADDR_IN ServerAddr;                           //分配端口及協(xié)議族并綁定  

            7.    ServerAddr.sin_family=AF_INET;                                  

            8.    ServerAddr.sin_addr.S_un.S_addr  =htonl(INADDR_ANY);            

            9.    ServerAddr.sin_port=htons(11111);        // 11111端口監(jiān)聽  

            10.                                      // 端口號可以隨意更改,但最好不要少于1024  

            11.    

            12.  bind(ListenSocket,(LPSOCKADDR)&ServerAddr, sizeof(ServerAddr)); // 綁定套接字  

            13.    

            14.  listen(ListenSocket, 5);                                   //開始監(jiān)聽  

            【第二步】接受一個入站的連接請求

              一個accept就完了,都是一樣一樣一樣一樣的啊~~~~~~~~~~

             至于AcceptEx的使用,在完成端口中我會講到,這里就先不一次灌輸這么多了,不消化啊^_^

            view plaincopy to clipboardprint?

            1.    AcceptSocket = accept (ListenSocket, NULL,NULL) ;   

            當(dāng)然,這里是我偷懶,如果想要獲得連入客戶端的信息(記得論壇上也常有人問到),accept的后兩個參數(shù)就不要用NULL,而是這樣

            view plaincopy to clipboardprint?

            1.    SOCKADDR_IN ClientAddr;                   // 定義一個客戶端得地址結(jié)構(gòu)作為參數(shù)  

            2.    int addr_length=sizeof(ClientAddr);  

            3.    AcceptSocket = accept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length);  

            4.    // 于是乎,我們就可以輕松得知連入客戶端的信息了  

            5.    LPCTSTR lpIP =  inet_ntoa(ClientAddr.sin_addr);      // 連入客戶端的 IP  

            6.    UINT nPort = ClientAddr.sin_port;                      // 連入客戶端的Port  

            【第三步】準(zhǔn)備好我們的重疊結(jié)構(gòu)

            有新的套接字連入以后,新建立一個WSAOVERLAPPED重疊結(jié)構(gòu)(當(dāng)然也可以提前建立好),準(zhǔn)備綁定到我們的重疊操作上去。這里也可以看到和上一篇中的明顯區(qū)別,就是不用再為WSAOVERLAPPED結(jié)構(gòu)綁定一個hEvent了。

            view plaincopy to clipboardprint?

            1. // 這里只定義一個,實(shí)際上是每一個SOCKET的每一個操作都需要綁定一個重疊結(jié)構(gòu)的,所以在實(shí)際使用面對多個客戶端的時候要定義為數(shù)組,詳見示例代碼;  
            2. WSAOVERLAPPED AcceptOverlapped   
            3. ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED));      // 置零  

                

            【第四步】開始在套接字上投遞WSARecv請求,需要將第三步準(zhǔn)備的WSAOVERLAPPED結(jié)構(gòu)和我們定義的完成例程函數(shù)為參數(shù)

            各個變量都已經(jīng)初始化OK以后,我們就可以開始進(jìn)行具體的Socket通信函數(shù)調(diào)用了,然后讓系統(tǒng)內(nèi)部的重疊結(jié)構(gòu)來替我們管理I/O請求,我們只用等待網(wǎng)絡(luò)通信完成后調(diào)用咱們的回調(diào)函數(shù)就OK了。

            這個步驟的重點(diǎn)就是 綁定一個Overlapped變量和一個完成例程函數(shù)

            view plaincopy to clipboardprint?

            1.   // WSAOVERLAPPED結(jié)構(gòu)指定為一個參數(shù),在套接字上投遞一個異步WSARecv()請求  

            2.   // 并提供下面的作為完成例程的_CompletionRoutine回調(diào)函數(shù)(函數(shù)名字)  

            3.   if(WSARecv(  

            4.       AcceptSocket,  

            5.       &DataBuf,  

            6.       1,  

            7.       &dwRecvBytes,  

            8.       &Flags,  

            9.       &AcceptOverlapped,  

            10.      _CompletionRoutine) == SOCKET_ERROR)  // 注意我們傳入的回調(diào)函數(shù)指針  

            11.      {  

            12.          if(WSAGetLastError() != WSA_IO_PENDING)  

            13.          {  

            14.              ReleaseSocket(nSockIndex);  

            15.              continue;  

            16.              }  

            17.          }  

            18.  }  

              

            【第五步】 調(diào)用WSAWaitForMultipleEvents函數(shù)或者SleepEx函數(shù)等待重疊操作返回的結(jié)果

              我們在前面提到過,投遞完WSARecv操作,并綁定了Overlapped結(jié)構(gòu)和完成例程函數(shù)之后,我們基本就是完事大吉了,等了系統(tǒng)自己去完成網(wǎng)絡(luò)通信,并在接收到數(shù)據(jù)的時候,會自動調(diào)用我們的完成例程函數(shù)。

              而我們在主線程中需要做的事情只有:做別的事情,并且等待系統(tǒng)完成了完成例程調(diào)用后的返回結(jié)果。

            就是說在WSARecv調(diào)用發(fā)起完畢之后,我們不得不在后面再緊跟上一些等待完成結(jié)果的代碼。有兩種辦法可以實(shí)現(xiàn):

            1)    和上一篇重疊I/O中講到的一樣,我們可以使用WSAWaitForMultipleEvent來等待重疊操作的事件通知, 方法如下:

            view plaincopy to clipboardprint?

            1.    // 因?yàn)?/span>WSAWaitForMultipleEvents() API要求  

            2.    // 在一個或多個事件對象上等待但是這個事件數(shù)組已經(jīng)不是和SOCKET相關(guān)聯(lián)的了  

            3.    // 因此不得不創(chuàng)建一個偽事件對象  

            4.    WSAEVENT EventArray[1];       

            5.    EventArray[0] = WSACreateEvent();                        // 建立一個事件  

            6.            ////////////////////////////////////////////////////////////////////////////////  

            7.    // 然后就等待重疊請求完成就可以了,注意保存返回值,這個很重要  

            8.    DWORD dwIndex = WSAWaitForMultipleEvents(1,EventArray,FALSE,WSA_INFINITE,TRUE);  

            這里參數(shù)的含義我就不細(xì)說了,MSDN上一看就明白,調(diào)用這個函數(shù)以后,線程就會置于一個警覺的等待狀態(tài),注意 fAlertable 參數(shù)一定要設(shè)置為 TRUE

            2)    可以直接使用SleepEx函數(shù)來完成等待,效果都是一樣的。

            SleepEx函數(shù)調(diào)用起來就簡單得多,它的函數(shù)原型定義是這樣的

                

            view plaincopy to clipboardprint?

            1. DWORD SleepEx(  
            2.              DWORD dwMilliseconds,  // 等待的超時時間,如果設(shè)置為INFINITE就會一直等待下去  
            3.              BOOL   bAlertable   // 是否置于警覺狀態(tài),如果為FALSE,則一定要等待超時時間完畢之后才會返回,這里我們是希望重疊操作一完成就能返回,所以同(1)一樣,我們一定要設(shè)置為TRUE  
            4.  );  

                調(diào)用這個函數(shù)的時候,同樣注意用一個DWORD類型變量來保存它的返回值,后面會派上用場。

            【第六步】通過等待函數(shù)的返回值取得重疊操作的完成結(jié)果

            這是我們最關(guān)心的事情,費(fèi)了那么大勁投遞的這個重疊操作究竟是個什么結(jié)果呢?就是通過上一步中我們調(diào)用的等待函數(shù)的DWORD類型的返回值,正常情況下,在操作完成之后,應(yīng)該是返回WAIT_IO_COMPLETION,如果返回的是 WAIT_TIMEOUT,則表示等待設(shè)置的超時時間到了,但是重疊操作依舊沒有完成,應(yīng)該通過循環(huán)再繼續(xù)等待。如果是其他返回值,那就壞事了,說明網(wǎng)絡(luò)通信出現(xiàn)了其他異常,程序就可以報錯退出了……

            判斷返回值的代碼大致如下:

            view plaincopy to clipboardprint?

            1. ///////////////////////////////////////////////////////////////////////////////////  
            2. // 返回WAIT_IO_COMPLETION表示一個重疊請求完成例程代碼的結(jié)束。繼續(xù)為更多的完成例程服務(wù)  
            3. if(dwIndex == WAIT_IO_COMPLETION)  
            4. {  
            5. TRACE("重疊操作完成...\n");  
            6. }  
            7. else if( dwIndex==WAIT_TIMEOUT )  
            8. {  
            9.      TRACE(“超時了,繼續(xù)調(diào)用等待函數(shù)”);  
            10. }  
            11. else  
            12. {  
            13.     TRACE(“廢了…”);  
            14. }  

             

            操作完成了之后,就說明我們上一個操作已經(jīng)成功了,成功了之后做什么?當(dāng)然是繼續(xù)投遞下一個重疊操作了啊…..繼續(xù)上面的循環(huán)。

             

            【第七步】繼續(xù)回到第四步,在套接字上繼續(xù)投遞WSARecv請求,重復(fù)步驟4-7

             大家可以參考我的代碼,在這里就先不寫了,因?yàn)楦魑欢家欢ū任?/span>smart,領(lǐng)悟了關(guān)鍵所在以后,稍作思考就可以靈活變通了。

             

            【第八步】“享受”接收到的數(shù)據(jù)

            朋友們看到這里一定會問,我忙活了這么久,那客戶端傳來的數(shù)據(jù)在哪里接收啊?怎么一點(diǎn)都沒有提到呢……

            這個問題問得好,我們寫了這么多代碼圖個什么呢?

            其實(shí)想要讀取客戶端的數(shù)據(jù)很簡單,因?yàn)槲覀冊?/span>WSARecv調(diào)用的時候,是傳遞了一個WSABUF的變量的,用于保存網(wǎng)絡(luò)數(shù)據(jù),而在我們寫的完成例程回調(diào)函數(shù)里面,就可以取到客戶端傳送來的網(wǎng)絡(luò)數(shù)據(jù)了。

            因?yàn)橄到y(tǒng)在調(diào)用我們完成例程函數(shù)的時候,其實(shí)網(wǎng)絡(luò)操作已經(jīng)完成了,WSABUF里面已經(jīng)有我們需要的數(shù)據(jù)了,只是通過完成例程來進(jìn)行后期的處理。具體可以參考示例代碼。 DataBuf.buf就是一個char*字符串指針,聽?wèi){你的處理吧,我就不多說了。

             

            一.         實(shí)際應(yīng)用中應(yīng)該完善的地方

            實(shí)我一直都很想把我以前做的工程中的代碼貼出來給大家分享,但是代碼實(shí)在是太繁雜了,僅僅把網(wǎng)絡(luò)通信的部分剝離出來,不經(jīng)過測試的話,肯定還會有其他的很 多問題,反而誤導(dǎo)了初學(xué)者,不過我的計劃是在寫下一個“完成端口”部分的時候,直接把項(xiàng)目中的一部分代碼拿出來試試看吧……

            總之網(wǎng)絡(luò)服務(wù)器端程序,在實(shí)際應(yīng)用的時候,關(guān)鍵的幾點(diǎn)就是:

            1)    要考慮到客戶端很多、通信量很大的時候,如何去處理,如何盡可能的減小開銷,提高效率;

            2)    多個線程之間共用一些變量的時候,一定要注意到同步問題;

            3)    作為一個網(wǎng)絡(luò)程序,出現(xiàn)異常是家常便飯,一定要把代碼寫得盡可能的健壯,要盡量全面的考慮處理各種各樣的錯誤;

            4)    盡量不要出現(xiàn)各種字符緩沖區(qū)的問題,寫安全的代碼,防止被黑客利用……(這點(diǎn)似乎扯遠(yuǎn)了,但是確實(shí)是一個很現(xiàn)實(shí)的問題)

                 其他的問題,還希望各位這方面的網(wǎng)絡(luò)專家使勁批評指正,因?yàn)榇a是很多年前的了,一定存在著很多的問題。

             

                                                                                                                                                       --- Finished at DLUT

                                                                                                                                                       --- 2009-02-16

             

             

             

            posted on 2009-09-04 15:48 ChinaPanda 閱讀(906) 評論(0)  編輯 收藏 引用


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


            亚洲国产精品嫩草影院久久| 久久99国产亚洲高清观看首页| 99久久夜色精品国产网站| 精品综合久久久久久888蜜芽| 亚洲国产精品无码久久SM| 7777精品伊人久久久大香线蕉 | 97久久久精品综合88久久| 国内精品人妻无码久久久影院导航 | 亚洲国产日韩欧美综合久久| 久久精品国产色蜜蜜麻豆| 亚洲国产精品久久久久网站| 久久成人影院精品777| AV色综合久久天堂AV色综合在| 久久夜色精品国产网站| 麻豆一区二区99久久久久| 精品国产乱码久久久久久郑州公司| 久久综合九色综合网站| 国产精品美女久久久久久2018| 99精品久久精品一区二区| 欧美久久精品一级c片片| 777久久精品一区二区三区无码| 亚洲精品高清久久| 久久精品国产一区二区三区| 美女久久久久久| 久久久久久精品久久久久| 久久久久久久久无码精品亚洲日韩 | 色诱久久av| 久久国产免费直播| 久久久久亚洲av无码专区| 狠狠色丁香婷婷综合久久来| 精品久久久久久国产免费了| 天天影视色香欲综合久久| 中文无码久久精品| 97久久国产亚洲精品超碰热| 国产精品99久久久久久猫咪| 一级做a爰片久久毛片毛片| 99久久精品免费看国产一区二区三区| 日韩人妻无码精品久久久不卡| 久久久久久综合一区中文字幕| 久久天天躁狠狠躁夜夜不卡 | 久久久噜噜噜久久中文福利|