最近,在微软负责VSTS2010 单元和负载测试这部分的Lonny在他的博文中写了一篇关于用户如何通过调用VSTS 2010里网络仿真(Network Emulation) 功能提供的API创建一个示例的网络仿真器, 本人尝试翻译成中文以方便大家一起学习和探讨,若有翻译不当之处敬请指正。您也可以访问Lonny 的blog看英文版

使用VSTS 2010 Beta1创建一个独立的网络仿真器(Network Emulator)

在 Visual Studio 10  Beta 1中我们发布了 “真实网络仿真”(Network Emulation),该版本允许您在运行测试时(例如,一个单元测试或负载测试中)模拟不同类型的网络。 然而,有一点未提及的是,它能够很容易地在未使用 Visual Studio Team System框架运行测试时模拟不同的网络。 例如,我可能想运行一个应用程序,看它在低带宽连接限制情况下如何运行。可能我并不想为此创建一个测试,只想用用它看它会发生什么情况。 要完成此“开箱即用”,我需要创建一个单元测试,让它在长时间内处于休眠状态,同时打开网络仿真。虽然这是相当容易的,但似乎有点不灵活。这篇文章将会集中在创建一个解决方案使得此过程简单到我只需要点击‘开始’按钮便启动网络仿真,当我要退出时只要按‘停止’按钮。

创建一个存根 (stub) 应用程序
• 创建网络仿真器的第一步中是:打开 Visual Studio 2010 并创建一个空的“ Windows 窗体应用 ”。
 
• 下一步是复制包含网络仿真 API 的程序集。此程序集为 “userapi.dll”,位于 %Program Files %\ Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies\DataCollectors\x86 (对于 64 位系统是x64)。拷贝该文件并将其放到该解决方案目录下,然后将它添加到解决方案,更改“拷贝到输出目录 ”为 “如果较新则拷贝” 
 

 创建一个用于保存简化的网络仿真 API 的类
在此版本的 Visual Studio 中,网络仿真 API 是本机代码。 因此,我们通过有限的方式从托管代码中去访问这个API。 在此示例中,我们会使用 PInvoke来调用API。 为了实现它,我们必须在使用他们之前为每个方法创建一些定义。


创建一个新的类名为 NativeNetworkEmulationAPI ,并添加以下声明:

*************************************************
using System;
using System.Runtime.InteropServices;
namespace StandaloneNetworkEmulation
{
    public class NativeNetworkEmulationAPI
    {
        [DllImport("userapi.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern int NEGetVersion(ref uint pdwVersion);
        [DllImport("userapi.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern int NEInitialize(ref uint pdwVersion, ref IntPtr phEmulator);
        [DllImport("userapi.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern int NECleanup(IntPtr hEmulator);
        [DllImport("userapi.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern int NEStartEmulation(IntPtr hEmulator);
        [DllImport("userapi.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
        public static extern int NEStopEmulation(IntPtr hEmulator, uint dwTimeout, int fForce);
        [DllImport("userapi.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        public static extern int NELoadProfile(IntPtr hEmulator,
            [MarshalAs(UnmanagedType.LPWStr)]
            string profileName);
    }
}

*************************************************

复制并修改预定义的网络配置文件
• 下一步是从 VS2010复制预定义的网络配置文件到我们自己的解决方案,以便我们可以修改它们并用于我们创建的独立仿真器中:
    a) 在解决方案中创建一个名为“Profile”的文件夹
    b) 将所有预定义的网络配置文件(位于 %Program Files %\ Microsoft Visual Studio 10.0   \Common7\IDE\Templates\LoadTest\Networks)复制到此文件夹
    c) 并为每个配置文件设置Build Action生成操作= “无”
• 配置文件设置完成后,为了使仿真器能正确地读取配置文件,需要对每个配置文件做少量修改:
    a) 打开每个配置文件
    b) 删除包含名为“NetworkEmulationProfile”(这应该是配置文件中的第一个和最后一个行)的两行。 例如:在“3G.network”文件中删除下列两行:
    o  <NetworkEmulationProfile name="3G" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
    o  </NetworkEmulationProfile>
     修改此配置文件后,最高一层的XML节点应该是 <Emulation>。
• 最后要注意是删除LAN.network 配置文件,因为仿真器不会使用它来模拟网络。它是我们的架构一种特殊情况,以表明要使用完整的可用网络带宽(换句话说就是不进行任何网络模拟)。


完成主窗体应用程序
下一步,在主窗体中添加开始和停止按钮,以及允许我们选择要用于网络模拟的配置文件的组合框。
 

为窗体添加成员变量
   1: private IntPtr m_emulatorHandle;

为窗体添加Load 事件处理程序,并添加以下代码:
   1: NativeNetworkEmulationAPI.NELoadProfile(m_emulatorHandle, Path.Combine("Profiles",
   2:     m_networkProfiles.SelectedText) + ".Network");
   3: if (0 == NativeNetworkEmulationAPI.NEStartEmulation(m_emulatorHandle))
   4: {
   5:     startButton.Enabled = false;
   6:     stopButton.Enabled = true;
   7: }
   8: else
   9: {
   10:     MessageBox.Show("There was an error starting the emulation.");
   11: }
 
为窗体添加FormClosed 事件处理程序,并添加下面的代码:
   1: if (0 != NativeNetworkEmulationAPI.NECleanup(m_emulatorHandle))
   2: {
   3:     MessageBox.Show("There was an error cleaning up the emulator.");
   4: }
 
为开始按钮添加Click 事件处理程序,并添加以下代码:
   1: NativeNetworkEmulationAPI.NELoadProfile(m_emulatorHandle, Path.Combine("Profiles",
   2:     m_networkProfiles.SelectedText) + ".Network");
   3: if (0 == NativeNetworkEmulationAPI.NEStartEmulation(m_emulatorHandle))
   4: {
   5:     startButton.Enabled = false;
   6:     stopButton.Enabled = true;
   7: }
   8: else
   9: {
   10:     MessageBox.Show("There was an error starting the emulation.");
   11:}


为停止按钮添加 Click 事件处理程序,并添加下面的代码:
   1: if (0 == NativeNetworkEmulationAPI.NEStopEmulation(m_emulatorHandle, 2000, 1))
   2: {
   3:     startButton.Enabled = false;
   4:     stopButton.Enabled = true;
   5: }
   6: else
   7: {
   8:     MessageBox.Show("There was an error stopping the emulation.");
   9: }
  10: startButton.Enabled = true;
  11: stopButton.Enabled = false;


结论
在这篇专题文章中,我们通过VS2010里网络仿真功能提供的API创建了一个示例的网络仿真器。 此示例虽简单,但我们可以使用此API做很多的事情,如包跟踪、 过滤等。 请继续关注我的博客,以后我会告诉你如何通过自定义配置文来执行网络仿真里一些高级的功能。

posted on 2009-07-03 11:55  SabrinaZheng  阅读(1107)  评论(0编辑  收藏  举报