• <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++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            FileZilla Server源碼分析(4)

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

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

                函數名都為紅色粗體,并且帶一對小括號,如果括號不含有字符“...”表示該函數無參數,否則有參數,具體什么參數不具體指明。變量均為黑色粗體。  


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

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

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

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

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

                下面再補充之前函數WindowProc(...)關于網絡事件的詳細處理,僅僅針對非代理層的處理:
            //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)//已綁定成功的設置為連接成功
                         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)) //獲取要可讀的字節數
                              nErrorCode = WSAGetLastError();
                         
            if (nErrorCode)
                              pSocket
            ->SetState(aborted);    //出錯
                         if (nBytes != 0 || nErrorCode != 0//通知socket已經有數據可以讀了
                              pSocket->OnReceive(nErrorCode);
                     }
                     
            break;
               
            case FD_FORCEREAD:
                   
            //除了不用獲取去可讀的字節數之外,完全可FD_READ一樣,這是作者自定義的類型
                     break;
               
            case FD_WRITE:
                   
            //前面的狀態判斷和FD_READ類似,不再詳述
                   if (pSocket->m_lEvent & FD_WRITE)
                   {
                        
            if (nErrorCode)
                            pSocket
            ->SetState(aborted);

                        pSocket
            ->OnSend(nErrorCode);//通知socket已經有數據可以發送了
                    }
                    
            break;
                
            case FD_CONNECT:
                    
            if (pSocket->GetState() == connecting)
                    {
                        
            if (nErrorCode && pSocket->m_SocketData.nextAddr)  //有多個地址?
                        {
                             
            if (pSocket->TryNextProtocol())  //嘗試下一個協議地址
                                  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:
                     
            //如果不是監聽或已經綁定狀態,跳出
                     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))
                     {
                          
            //作者的注釋很清楚,如果關閉的時候還有數據可讀,將當前pSocket->m_SocketData.onCloseCalled 設置為TRUE
                          
            //以表示需要再一次調用關閉函數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;
               }
            //}

               本節是對第二節的一個小補充,也算是對MS的CAsyncSocket類的一個另類剖析吧。
            久久本道久久综合伊人| 香蕉久久AⅤ一区二区三区| 久久无码人妻一区二区三区午夜| 久久人人爽人人爽人人片AV东京热 | 精品久久久久久无码免费| 狠狠久久综合| 蜜臀久久99精品久久久久久小说| 国产精品久久久久国产A级| 中文字幕成人精品久久不卡| 欧洲国产伦久久久久久久| 亚洲AV无码久久精品色欲| 精品无码人妻久久久久久| 99久久无色码中文字幕人妻| 欧美伊香蕉久久综合类网站| 性做久久久久久久久久久| 国产69精品久久久久777| 久久久国产99久久国产一| 一本久久久久久久| 久久99国产乱子伦精品免费| 亚洲国产成人乱码精品女人久久久不卡| 久久久久亚洲AV成人网人人网站 | 91精品国产综合久久四虎久久无码一级| 人人狠狠综合久久亚洲高清| 国产亚洲欧美成人久久片| 一本色道久久综合亚洲精品| 久久亚洲精品国产亚洲老地址| 精品久久久无码中文字幕| 久久精品国产精品国产精品污| 日韩人妻无码精品久久免费一 | 久久777国产线看观看精品| 久久精品国产亚洲AV蜜臀色欲| 精品久久久久一区二区三区| 99热都是精品久久久久久| 国产成人精品久久亚洲高清不卡| 国产成人久久精品激情| 99久久免费国产精品热| 99久久精品日本一区二区免费| 精品久久久久久国产潘金莲 | 亚洲人成伊人成综合网久久久| 色婷婷久久久SWAG精品| 青青草国产97免久久费观看|