• <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類的一個另類剖析吧。
            九九久久自然熟的香蕉图片| 精品久久8x国产免费观看| 久久久久久狠狠丁香| 伊人久久综在合线亚洲2019| 精品国产综合区久久久久久 | 色综合久久88色综合天天 | 久久久中文字幕日本| 亚洲伊人久久成综合人影院| 亚洲精品乱码久久久久久按摩| 久久久久人妻一区精品色| 久久久久夜夜夜精品国产| 久久国产午夜精品一区二区三区| 久久亚洲国产最新网站| 久久精品国产亚洲av日韩| 国产免费久久精品丫丫| 精品久久久久久国产| 99国内精品久久久久久久| 77777亚洲午夜久久多喷| 国产综合免费精品久久久| 久久精品国产99久久久古代| 99精品久久久久久久婷婷| 色综合久久中文字幕无码| 久久久久成人精品无码| 久久婷婷五月综合色高清| 欧美日韩精品久久久久| 久久久九九有精品国产| 日韩精品久久无码人妻中文字幕| 久久本道久久综合伊人| 国产午夜久久影院| 久久综合精品国产二区无码| 一本久久综合亚洲鲁鲁五月天| 久久精品一区二区国产| 色综合久久久久无码专区 | 亚洲综合久久夜AV | 91亚洲国产成人久久精品| 久久久久久毛片免费播放| 久久综合久久性久99毛片| 久久夜色精品国产www| 久久亚洲国产精品123区| 免费一级欧美大片久久网 | 久久久久久亚洲Av无码精品专口 |