• <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糟 閱讀(1229) 評論(0)  編輯 收藏 引用 所屬分類: 開源

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

                函數(shù)名都為紅色粗體,并且?guī)б粚π±ㄌ枺绻ㄌ柌缓凶址?#8220;...”表示該函數(shù)無參數(shù),否則有參數(shù),具體什么參數(shù)不具體指明。變量均為黑色粗體。  


                首先來看一下該類的構(gòu)造函數(shù)CAsyncSocketEx(),構(gòu)造函數(shù)完成的是部分成員變量的初始化工作,其中最重要的是一個結(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;

                每個成員具體作用注釋已經(jīng)比較清楚地說明了,后面用到的時候再指出。除了層NOLAYERS編譯(如果不明白,請看第二篇)此外還有一個宏條件編譯需要注意
            #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記錄中移除掉這個socket,之后就是銷毀各種資源如地址、代理層等,有一個細(xì)節(jié),不明白的可以MSDN,不細(xì)說了。
               if (m_hAsyncGetHostByNameHandle)
                    WSACancelAsyncRequest(m_hAsyncGetHostByNameHandle);
                m_hAsyncGetHostByNameHandle 
            = NULL;

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

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

                下面再補(bǔ)充之前函數(shù)WindowProc(...)關(guān)于網(wǎng)絡(luò)事件的詳細(xì)處理,僅僅針對非代理層的處理:
            //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);    //出錯
                         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)  //有多個地址?
                        {
                             
            if (pSocket->TryNextProtocol())  //嘗試下一個協(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ù)據(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é)是對第二節(jié)的一個小補(bǔ)充,也算是對MS的CAsyncSocket類的一個另類剖析吧。
            国产精品美女久久久久AV福利 | 93精91精品国产综合久久香蕉| 伊人久久综合成人网| 国内精品伊人久久久久| 国产成人精品久久亚洲| 99精品国产免费久久久久久下载| 亚洲中文字幕久久精品无码APP| 久久w5ww成w人免费| 久久97久久97精品免视看秋霞| 精品国产乱码久久久久久人妻| 色综合久久中文综合网| 精品无码久久久久国产动漫3d | 久久精品亚洲乱码伦伦中文| 国内精品人妻无码久久久影院导航 | 精品国产福利久久久| 亚洲AⅤ优女AV综合久久久| 99久久无色码中文字幕| 欧美久久一区二区三区| 精品视频久久久久| 精品国产VA久久久久久久冰| 亚洲欧美成人久久综合中文网 | 久久一区二区免费播放| 久久青青草原国产精品免费| 亚洲国产另类久久久精品小说| 久久久久久国产精品免费免费| 久久人妻少妇嫩草AV无码专区| 久久综合色之久久综合| 99久久免费只有精品国产| 狠狠狠色丁香婷婷综合久久俺| 国产精品99久久久精品无码| 亚洲欧美一级久久精品| 一本色综合久久| 一日本道伊人久久综合影| 中文字幕无码久久精品青草 | 久久这里都是精品| 久久偷看各类wc女厕嘘嘘| 精品乱码久久久久久夜夜嗨| 97久久国产综合精品女不卡| 久久不射电影网| 国产精品九九久久精品女同亚洲欧美日韩综合区 | 国产精品无码久久四虎|