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

            大漠落日

            while(!dead) study++;
            posts - 46, comments - 126, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            FileZilla Server源碼分析(4)

            Posted on 2010-06-25 11:11 亂78糟 閱讀(1219) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 開源

                本節(jié)的分析是基于本系列第二篇FileZilla Server源碼分析(2之上,嚴(yán)格意義上來說是更為詳細(xì)的分析,深入了解CAsyncSocketEx的實(shí)現(xiàn),我將挑出重要的函數(shù)一一分析。

                函數(shù)名都為紅色粗體,并且?guī)б粚?duì)小括號(hào),如果括號(hào)不含有字符“...”表示該函數(shù)無參數(shù),否則有參數(shù),具體什么參數(shù)不具體指明。變量均為黑色粗體。  


                首先來看一下該類的構(gòu)造函數(shù)CAsyncSocketEx(),構(gòu)造函數(shù)完成的是部分成員變量的初始化工作,其中最重要的是一個(gè)結(jié)構(gòu)體變量m_SocketData,它的原型為:
               
                //Strucure to hold the socket data
                struct t_AsyncSocketExData
                {
                    SOCKET hSocket; 
            //Socket handle
                    int nSocketIndex; //Index of socket, required by CAsyncSocketExHelperWindow
                    int nFamily;
                    addrinfo 
            *addrInfo, *nextAddr; // Iterate through protocols on connect failure
                    bool onCloseCalled; // Set to true on first received OnClose event
                } m_SocketData;

                還有m_pLocalAsyncSocketExThreadData的原型為:
            //Pointer to the data of the local thread
                struct t_AsyncSocketExThreadData
                {
                    CAsyncSocketExHelperWindow 
            *m_pHelperWindow;
                    
            int nInstanceCount;
                    DWORD nThreadId;
                    std::list
            <CAsyncSocketEx*> layerCloseNotify;
                } 
            *m_pLocalAsyncSocketExThreadData;

                每個(gè)成員具體作用注釋已經(jīng)比較清楚地說明了,后面用到的時(shí)候再指出。除了層NOLAYERS編譯(如果不明白,請(qǐng)看第二篇)此外還有一個(gè)宏條件編譯需要注意
            #ifndef NOSOCKETSTATES
                m_nPendingEvents 
            = 0//socket當(dāng)前未決的網(wǎng)絡(luò)事件,例如FD_READ
                m_nState = notsock; //socket當(dāng)前狀態(tài)
            #endif //NOSOCKETSTATES

                析構(gòu)函數(shù)~CAsyncSocketEx()調(diào)用函數(shù)Close()關(guān)閉socket,并調(diào)用FreeAsyncSocketExInstance()做清理工作。
                Close()函數(shù)中關(guān)閉層m_pFirstLayer->Close(),之后關(guān)閉成員變量m_SocketData.hSocket并且從輔助窗口m_pLocalAsyncSocketExThreadData->m_pHelperWindow記錄中移除掉這個(gè)socket,之后就是銷毀各種資源如地址、代理層等,有一個(gè)細(xì)節(jié),不明白的可以MSDN,不細(xì)說了。
               if (m_hAsyncGetHostByNameHandle)
                    WSACancelAsyncRequest(m_hAsyncGetHostByNameHandle);
                m_hAsyncGetHostByNameHandle 
            = NULL;

                再說FreeAsyncSocketExInstance()之前先說對(duì)應(yīng)的函數(shù)InitAsyncSocketExInstance(),這兩個(gè)函數(shù)干的活都和一個(gè)static變量m_spAsyncSocketExThreadDataList有關(guān),一個(gè)初始化,一個(gè)銷毀m_pLocalAsyncSocketExThreadData保存了當(dāng)前線程的id和輔助窗口的指針。

                Create(...)函數(shù)創(chuàng)建代理層或者自身的socket以及做綁定到輔助窗口等操作。如果定義了使用代理層,那么所有關(guān)于socket的操作都會(huì)被代理層攔截,如create,listen,connect,accpet,recv,send,但是不包括bind,因?yàn)榇韺觕reate的時(shí)候已經(jīng)提前綁定過了。
                TriggerEvent(...)這個(gè)函數(shù)用來觸發(fā)程序員指定的網(wǎng)絡(luò)事件,例如CControlSocket類中的Send(...)函數(shù)就調(diào)用了TriggerEvent(FD_WRITE)來觸發(fā)寫操作。它通過PosetMessage給輔助窗口,然后窗口通過消息處理函數(shù)WindowProc(...)處理這種種消息(詳細(xì)請(qǐng)參考第二節(jié))。
               
                與代理層相關(guān)的函數(shù),如AddLayer(...)RemoveAllLayers()等,還有設(shè)置獲取各種信息的函數(shù)如GetSockOpt()就不在詳述了。

                下面再補(bǔ)充之前函數(shù)WindowProc(...)關(guān)于網(wǎng)絡(luò)事件的詳細(xì)處理,僅僅針對(duì)非代理層的處理:
            //if (!pSocket->m_pFirstLayer)
            //{
               switch (nEvent)
               {
                
            case FD_READ:
                   
            if (pSocket->GetState() == connecting && !nErrorCode)
                    {
                        pSocket
            ->m_nPendingEvents |= FD_READ; //如果正在連接,那么將讀事件加入未決事件變量里
                        break;
                    }
                    
            else if (pSocket->GetState() == attached)//已綁定成功的設(shè)置為連接成功
                         pSocket->SetState(connected);
                    
            if (pSocket->GetState() != connected)    //如果還沒有連接成功,跳出
                         break;

                    
            // Ignore further FD_READ events after FD_CLOSE has been received
                    if (pSocket->m_SocketData.onCloseCalled)
                        
            break;
                    
            if (pSocket->m_lEvent & FD_READ)
                    {
                         DWORD nBytes 
            = 0;
                         
            if (!nErrorCode)
                         
            if (!pSocket->IOCtl(FIONREAD, &nBytes)) //獲取要可讀的字節(jié)數(shù)
                              nErrorCode = WSAGetLastError();
                         
            if (nErrorCode)
                              pSocket
            ->SetState(aborted);    //出錯(cuò)
                         if (nBytes != 0 || nErrorCode != 0//通知socket已經(jīng)有數(shù)據(jù)可以讀了
                              pSocket->OnReceive(nErrorCode);
                     }
                     
            break;
               
            case FD_FORCEREAD:
                   
            //除了不用獲取去可讀的字節(jié)數(shù)之外,完全可FD_READ一樣,這是作者自定義的類型
                     break;
               
            case FD_WRITE:
                   
            //前面的狀態(tài)判斷和FD_READ類似,不再詳述
                   if (pSocket->m_lEvent & FD_WRITE)
                   {
                        
            if (nErrorCode)
                            pSocket
            ->SetState(aborted);

                        pSocket
            ->OnSend(nErrorCode);//通知socket已經(jīng)有數(shù)據(jù)可以發(fā)送了
                    }
                    
            break;
                
            case FD_CONNECT:
                    
            if (pSocket->GetState() == connecting)
                    {
                        
            if (nErrorCode && pSocket->m_SocketData.nextAddr)  //有多個(gè)地址?
                        {
                             
            if (pSocket->TryNextProtocol())  //嘗試下一個(gè)協(xié)議地址
                                  break;
                         }
                             pSocket
            ->SetState(connected);
                    }
                    
            else if (pSocket->GetState() == attached && !nErrorCode)
                         pSocket
            ->SetState(connected);
                    
            if (pSocket->m_lEvent & FD_CONNECT)
                         pSocket
            ->OnConnect(nErrorCode);
                    
            if (!nErrorCode)
                    {
                         
            //判斷未決事件中是否期望的讀寫事件,如果有,通知socket
                         if ((pSocket->m_nPendingEvents&FD_READ) && pSocket->GetState() == connected)
                             pSocket
            ->OnReceive(0);
                         
            if ((pSocket->m_nPendingEvents&FD_FORCEREAD) && pSocket->GetState() == connected)
                             pSocket
            ->OnReceive(0);
                         
            if ((pSocket->m_nPendingEvents&FD_WRITE) && pSocket->GetState() == connected)
                              pSocket
            ->OnSend(0);
                     }
                     pSocket
            ->m_nPendingEvents = 0;
                     
            break;
                
            case FD_ACCPET:
                     
            //如果不是監(jiān)聽或已經(jīng)綁定狀態(tài),跳出
                     if (pSocket->GetState() != listening && pSocket->GetState() != attached)
                          
            break;
                     
            if (pSocket->m_lEvent & FD_ACCEPT)
                          pSocket
            ->OnAccept(nErrorCode);//通知
                     break;
                
            case FD_CLOSE:
                     
            //沒有連接或綁定,跳出
                     if (pSocket->GetState() != connected && pSocket->GetState() != attached)
                          
            break;

                     
            // If there are still bytes left to read, call OnReceive instead of
                     
            // OnClose and trigger a new OnClose
                     DWORD nBytes = 0;
                     
            if (!nErrorCode && pSocket->IOCtl(FIONREAD, &nBytes))
                     {
                          
            //作者的注釋很清楚,如果關(guān)閉的時(shí)候還有數(shù)據(jù)可讀,將當(dāng)前pSocket->m_SocketData.onCloseCalled 設(shè)置為TRUE
                          
            //以表示需要再一次調(diào)用關(guān)閉函數(shù)OnClose
                          if (nBytes > 0)
                          {
                               
            // Just repeat message.
                               PostMessage(hWnd, message, wParam, lParam);
                               pSocket
            ->m_SocketData.onCloseCalled = true;                               
                               pSocket
            ->OnReceive(WSAESHUTDOWN);
                               
            break;
                           }
                      }

                      pSocket
            ->SetState(nErrorCode?aborted:closed);
                      pSocket
            ->OnClose(nErrorCode);
                      
            break;
               }
            //}

               本節(jié)是對(duì)第二節(jié)的一個(gè)小補(bǔ)充,也算是對(duì)MS的CAsyncSocket類的一個(gè)另類剖析吧。
            欧美777精品久久久久网| 久久久久亚洲精品男人的天堂| 人妻精品久久久久中文字幕69| 久久99国产精品一区二区| 精品久久久久久无码人妻蜜桃| 精品久久久久久久久免费影院| 久久精品一本到99热免费| 99久久伊人精品综合观看| 国产偷久久久精品专区| segui久久国产精品| 久久国产免费观看精品3| 色偷偷91久久综合噜噜噜噜| 99久久人妻无码精品系列蜜桃| 亚洲中文字幕伊人久久无码| 国产一区二区三区久久| 久久精品一本到99热免费| 国产成人精品久久亚洲高清不卡| 久久精品国产亚洲AV影院| 精品一久久香蕉国产线看播放 | 狠狠色丁香久久婷婷综| 伊人色综合久久天天网| 国内精品久久久久久久久电影网 | 国产精品18久久久久久vr| 热RE99久久精品国产66热| 久久精品国产99国产精品澳门| 色婷婷综合久久久中文字幕 | A狠狠久久蜜臀婷色中文网| 久久狠狠爱亚洲综合影院| 亚洲精品高清一二区久久| 久久成人精品| 国产叼嘿久久精品久久| 国产91久久综合| 精品久久综合1区2区3区激情| 久久精品国产精品国产精品污| 久久精品水蜜桃av综合天堂| 色偷偷久久一区二区三区| 亚洲精品乱码久久久久久久久久久久 | 久久夜色精品国产www| 国内精品久久久久久久影视麻豆| 中文字幕成人精品久久不卡| 国产精品狼人久久久久影院|