工具對比_模擬慢網速環境

 

出於工作需要,有時候需要模擬用戶的慢網速對產品做進一步測試&優化,目前有三個軟件可以模擬慢網速:Fiddler,NetLimiter,Network Delay Simulator。應該還有更多好用的軟件尚待發掘。

 

Fiddler 免費軟件。模擬網速功能比較單一(Rules --> Performance --> Simulate Modem speed),選項較少,Fiddler僅是減緩帶寬並未引入包丟失(後面的Network Delay Simulator加入了包丟失模擬)。且因爲瀏覽器併發連接數問題,會造成(Http watch 或Firebug)測試結果的瀑布圖不準。所以雖然有這個功能,咱們一般不用它。fiddler的亮點在另一方面

 

NetLimiter 共享軟件,需要自己註冊。準確的說是一款網絡流量控制軟件,通過它,你可以直接來控制每個程序對Internet的訪問以及流量分配情況。這裏有前人制作的圖。

 

Network Delay Simulator  免費軟件,下載地址 。我正在使用的,三種之中功能最強大,監聽Network Interface Card (NIC)和TCP/IP stack之間的網絡流量,可以模擬延時、帶寬甚至丟包率,更精確地模擬慢網速環境。設置也很簡單方便:輸入帶寬,點擊Save Flow即可,如果你要模擬丟包,填下丟包率便行。見圖。

 

 還有更專業的~~~~

工具推薦中指出Fiddler的“Simulate Modem Speeds”功能(Rules->Performance-> Simulate Modem Speeds)是延時,下面具體分析其實現:

Fiddler2\Scripts\SampleRules.js中設置腳本規則

static function OnBeforeRequest(oSession: Session)

{

     if (m_SimulateModem){

     // Delay sends by 300ms per KB uploaded.

     oSession["request-trickle-delay"] = "300";

     }

 

static function OnBeforeResponse(oSession: Session)

{

if (m_SimulateModem){

     // Delay receives by 150ms per KB downloaded.

     oSession["response-trickle-delay"] = "150";

}

 

實現代碼則在Fiddler.exe中的ServerChatter

public bool ResendRequest()

{

....

  if (this.m_session["request-trickle-delay"] != null)

  {

      int iMS = int.Parse(this.m_session.oFlags["request-trickle-delay"]);

      this.pipeServer.TrickleSend(0x400, iMS, this.m_session.oRequest.headers.ToByteArray(true, true, this._bWasForwarded && !this.m_session.isHTTPS));

      this.pipeServer.TrickleSend(0x400, iMS, this.m_session.requestBodyBytes);

   }

....

 

Fiddler.exe中的Session

public bool ReturnResponse(bool bKeepNTLMSockets)

{

    …

    try

    {

        if ((this.oRequest.pipeClient != null) && this.oRequest.pipeClient.Connected)

        {

            if (this.oFlags["response-trickle-delay"] != null)

            {

                int iMS = int.Parse(this.oFlags["response-trickle-delay"]);

                this.oRequest.pipeClient.TrickleSend(0x400, iMS, this.oResponse.headers.ToByteArray(true, true));

                if (this.responseBodyBytes != null)

                {

                    this.oRequest.pipeClient.TrickleSend(0x400, iMS, this.responseBodyBytes);

                }

            }

 

可以看到它們都用到了Fiddler.exe中類Pipe的函數TrickleSend,以下是其定義:

public void TrickleSend(int iSize, int iMS, byte[] data)

{

    for (int i = 0; i < data.Length; i += iSize)

    {

        Thread.Sleep((int) (iMS / 2));

        this.Send(data, i, iSize);

        Thread.Sleep((int) (iMS / 2));

    }

}

由此可見Fiddler.exe在請求和發送的每KB過程中都採取了延時模擬。關於延時,Issues with Time Warner Cable service in New York中有人說道”With the modem doing some QoS, it can maintain 150-300ms latency when uploading and downloading and the line remains pretty snappy.”BT Highway中也有類似描述。作者給出了如下解釋These speeds were derived from a simple model of the effective throughput of a modem.You can adjust these to match any other connection speed you want, so long as such speed is slower than how you're actually connected to the network, of course.The neXpert plugin for Fiddler does response-time predictions using data from Microsoft Research. 

Fiddler無法模擬瀏覽器併發連接數限制,開啓工具欄上的"Streaming"模式可以解決,但這樣就打破了規則"Simulate Modem speeds",得出來的總體時間大幅縮短,此時Fiddler不僅延時了帶寬還延時了瀏覽器併發連接。正如作者所說Fiddler僅是減緩帶寬並未引入包丟失。

 

Speed Simulator看起來比Fiddler模擬的差不多(注意:多做幾次測試,找一個穩定的結果,每次選擇HttpWatchTools->Clear Cache and All Cookied清空MSIE):


 
 

 

 

 

 

本想用同樣方法測試瀏覽器插件IE Throttle,結果它無法在x64 Windows XP SP2上的x86 IE中打開“IE Throttle Settings”。同類型的還有Firefox Throttle

 

Network Delay Simulator(簡稱NetSim)採用Token BucketLeaky_bucket算法模擬真實網絡並監聽網卡和Tcp/IP之間的網絡流量,詳見Is there any forum for Net Simulator顯然,它採用的是網絡包丟失模擬但需要注意這款免費軟件從version 0.9.129開始支持x86 Windows 到Win7,關於此軟件任何問題可聯繫Andrew 

HP推薦ShunraVE DesktopWAN emulation使用運行在FreeBSD上的免費Dummynet

 

ToDo:

HP LoadrunnerSpeed Simulation如何?MS VSTS 2010Network Emulation又如何?

 由於測不準,我們得不到準確的結果,但可以得到儘可能精確的結果。比如modem,你能確定國內中國電信、中國網通等ISP提供給終端用戶的無論何時何地都是標準的速度56k嗎?也許KeynoteGomez提供的服務,Google AnalyticsOmnitureWebtrendsWebPagetest運營監控是一種彌補措施。 【關於Fiddler其它】1. 通過WinINET設置Proxy轉發給127.0.0.1:8888public bool Attach()
{
    if (!this._bIsAttached)
    {
        this.oAllConnectoids = new WinINETConnectoids();
        this.piPrior = this.oAllConnectoids.GetDefaultConnectionGatewayInfo();
        if ((this.piPrior.sHttpProxy != null) && this.piPrior.sHttpProxy.Contains(CONFIG.sFiddlerListenHostPort))
        {
            this.piPrior.sHttpProxy = null;
            this.piPrior.sHttpsProxy = null;
            this.piPrior.bUseManualProxies = false;
            this.piPrior.bAllowDirect = true;
        }
        if (CONFIG.bForwardToGateway && ((this.piPrior.sPACScriptLocation != null) || this.piPrior.bAutoDetect))
        {
            this.oAutoProxy = new WinHTTPAutoProxy(this.piPrior.bAutoDetect, this.piPrior.sPACScriptLocation);
        }
        if (CONFIG.bForwardToGateway && this.piPrior.bUseManualProxies)
        {
            this._ipepHttpGateway = Utilities.IPEndPointFromHostPortString(this.piPrior.sHttpProxy);
            this._ipepHttpsGateway = Utilities.IPEndPointFromHostPortString(this.piPrior.sHttpsProxy);
            this._ipepFtpGateway = Utilities.IPEndPointFromHostPortString(this.piPrior.sFtpProxy);
            if (this.piPrior.sHostsThatBypass != null)
            {
                this.oBypassList = new ProxyBypassList(this.piPrior.sHostsThatBypass);
                if (!this.oBypassList.HasEntries)
                {
                    this.oBypassList = null;
                }
            }
        }
        else
        {
            this._ipepFtpGateway = this._ipepHttpGateway = this._ipepHttpsGateway = null;
        }
        WinINETProxyInfo oNewInfo = new WinINETProxyInfo();
        if (CONFIG.bHookWithPAC)
        {
            oNewInfo.bAllowDirect = true;
            oNewInfo.sPACScriptLocation = "file://" + CONFIG.GetPath("Pac");
        }
        else
        {
            oNewInfo.bUseManualProxies = true;
            oNewInfo.bAllowDirect = true;
            oNewInfo.sHttpProxy = CONFIG.sFiddlerListenHostPort;
            if (CONFIG.bCaptureCONNECT)
            {
                oNewInfo.sHttpsProxy = CONFIG.sFiddlerListenHostPort;
            }
            else
            {
                oNewInfo.sHttpsProxy = this.piPrior.sHttpsProxy;
            }
            if (this.piPrior.bUseManualProxies)
            {
                oNewInfo.sFtpProxy = this.piPrior.sFtpProxy;
                oNewInfo.sSocksProxy = this.piPrior.sSocksProxy;
            }
            if (CONFIG.bCaptureFTP)
            {
                oNewInfo.sFtpProxy = CONFIG.sFiddlerListenHostPort;
            }
            oNewInfo.sHostsThatBypass = CONFIG.sHostsThatBypassFiddler;
        }
        if (this.oAllConnectoids.HookConnections(oNewInfo))
        {
            this._bIsAttached = true;
            FiddlerApplication.OnFiddlerAttach();
            this.WriteAutoProxyPACFile(true);
        }
        else
        {
            FiddlerApplication.DoNotifyUser("Failed to register Fiddler as the system proxy.", "Error");
            _setDynamicRegistryKey(false);
            return false;
        }
        _setDynamicRegistryKey(true);
    }
    return true;
}
 2.DNSTimeFiddler.exe函數HTTPSTunnel.TunnelDirectly,Session.ExecuteHTTPSConnect,ServerChatter.ConnectToHostServerChatter.ConnectToHost中:
int num3 = Environment.get_TickCount();
iPAddress = DNSResolver.GetIPAddress(str2, true);
this.m_session.Timers.DNSTime = Environment.get_TickCount() - num3;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章