点击打开链接

背景

在开发3G项目的是时候,发现尽管3G网络连接已经建立成功了,但是数据不能发送成功,查明原因,由于路由表的问题,导致数据往ActiveSync连接的对端,也就是PC发送,而不是发送到3G网络的拨号服务器去。本文讲述如何使用OpenNETCF来修改路由表。

什么是路由表(Routing Table)

先看一个Window Embedded CE的路由表

路由表是存储在路由器或者联网计算机上的一个电子表格或者数据库。本来路由表不仅仅使用在TCP/IP网络,IPX也使用路由表。但是目前流行使用路由表的网络只有TCP/IP。在TCP/IP网络,这表格指定IP包的流向,如上图可见,Destination和Netmask表示需要发送的目的地和及其掩码。GatewayAddress表示该Destination的包需要发送到的网关。Interface表示本机上网卡的地址,这个地址和Destination可以直接通信。Metric表示发送包的成本,是一个从0到9999的整数,数值越低表示成本越低,这条路径越可靠。

问题

当我拨通3G网络的时候,还是ping不通google,如下图:

原因出在路由表上,如下图:

google的地址是66.102.11.99,不在路由表内,会走默认路由,也就是0.0.0.0的路由配置.但是默认路由确有两条,而且Metric都是一样的。通过老王(王坚)的指导,那样的情况下,Windows 会自动选择速率快的网卡来传输数据,由于192.168.55.100是USB的ActiveSync连接,而10.250.47.212是3G网络连接,由于USB速度比3G网络快,所以发送到google.com(66.102.11.99)的包被默认发送到192.168.55.100去了。而192.168.55.100没有帮这台Wince机器做往internet的路由,所以wince机器没办法ping通google。

方案

解决这个问题可以有几个方案。

方案一,为目标地址加上路由,例如为google.com(66.102.11.99)加上路由,让它走10.250.47.212出,但是这方案不好,因为我的应用配置都是DNS名字,以后不知道到底IP是怎样,所以没办法为特定IP加路由。

方案二,删除指向192.168.55.100的默认路由。这个方案能满足我的需求,但是有时候需要用回ActiveSync的话需要增加原有的路由。

方案三,修改Metric的值,使得指向192.168.55.100的模拟路由优先选择。我的做法就是使用这个方案的。

实现

OpenNETCF的IPRoutingTable类大大简化了路由表开发的难度。

IPRoutingTable是一个容器类,封装了一个路由表格,每一条单独记录由IPForwardEntry类表达。IPForwardEntry类如下图所示。

IPForwardEntry类表示路由表中单独的一条记录。IPRoutingTable可以查看,新增,删除和修改路由表里面的项。其实增删改查路由表的操作都是通过P/Invoke iphlpapi.dll的API来完成的,关于P/Invoke 可以查看我之前的文章。关键API如下:

        [DllImport("iphlpapi.dll", SetLastError = true)]
        internal static unsafe extern int DeleteIpForwardEntry(byte[] pRoute);

[DllImport("iphlpapi.dll", SetLastError = true)]
        internal static unsafe extern int CreateIpForwardEntry(byte[] pRoute);

[DllImport("iphlpapi.dll", SetLastError = true)]
        internal static unsafe extern int SetIpForwardEntry(byte[] pRoute);

[DllImport("iphlpapi.dll", SetLastError = true)]
        internal static unsafe extern int GetIpForwardTable(IntPtr pIpForwardTable, ref int pdwSize, int bOrder);

[DllImport("iphlpapi.dll", SetLastError = true)]
        internal static unsafe extern int GetIpForwardTable(byte[] pIpForwardTable, ref int pdwSize, int bOrder);

[DllImport("iphlpapi.dll", SetLastError = true)]
        internal static unsafe extern int FlushIpNetTable(int dwIfIndex);

下面是我的实现代码,选择的是方案三。

代码

上面是整个程序的代码。下面分开讲一下。通过Singleton可以取出当前机器上的路由表信息。

显示

IPRoutingTable table = IPRoutingTable.GetRoutingTable();

取出IPRoutingTable下的IPForwardEntry 就可以显示整个路由表信息。

        static void Display(IPRoutingTable table)
        {
            Console.WriteLine("\r\n*IP Routing Table\r\n====================");
            Console.WriteLine(string.Format("{0}{1}{2}{3}{4}",
                "[Destination]".PadLeft(15),
                "[NetMask]".PadLeft(15),
                "[Next Hop]".PadLeft(15),
                "[Interface]".PadLeft(15),
                "[Metric]".PadLeft(12)));
            
            foreach (IPForwardEntry entry in table)
            {
                string interfaceName;
                if(entry.NetworkInterface == null)
                {
                    interfaceName = "127.0.0.1";
                }
                else
                {
                    interfaceName = entry.NetworkInterface.CurrentIpAddress.ToString();
                }

Console.WriteLine(string.Format("{0}{1}{2}{3}{4}",
                    entry.Destination.ToString().PadLeft(15),
                    entry.SubnetMask.ToString().PadLeft(15),
                    entry.NextHop.ToString().PadLeft(15),
                    interfaceName.PadLeft(15),
                    entry.Metric.ToString().PadLeft(12)));

if (entry.Destination.Equals(DefaultRoute))
                {
                    if (entry.NextHop.Equals(ActiveSyncIP))
                    {
                        activeSyncRouteMetric = entry.Metric;
                    }

IPForwardEntry tempEntry = entry.Clone();
                    routeEntries.Add(tempEntry);
                }
            }
        }

显示当前机器上所有的路由信息。

删除

Windows Embedded CE和PC对删除的操作有区别,在Wince下只能删除一个Destination,而PC可以删除指向这一Destination的网关。所以在Wince下删除指向这一Destination的网关不方便,需要先删除所有的,然后增加不想删除的。下面的语句是删除操作。

table.Remove(DefaultRoute);

删除默认路由后的路由信息。

修改

可以直接修改路由表项(IPForwardEntry)信息的属性。

entry.Metric = activeSyncRouteMetric - 1;

新增

新增就是把IPForwardEntry增加到IPRoutingTable里面

table.Add(entry);

新增默认路由后的路由表信息。

我把3G链接的路由项的Metric修改成49,这样会优先走这条路由信息。这样就能ping通google了。

最近不是很顺利,放个转运风车,点一下转转运。Cheer up.

在Window Embedded CE(Wince)下使用OpenNETCF进行路由表的开发的更多相关文章

  1. Windows Mobile和Wince(Windows Embedded CE)的字符集问题

    背景 开发过Windows Mobile和Wince(Windows Embedded CE)的开发者,特别是Native C++开发者,或多或少都遇到过ANSI字符集和Unicode字符集的转换问题 ...

  2. Windows Embedded CE 6.0开发环境的搭建

    最近开始在学习嵌入式,在这里首先得安装Windows Embedded CE 6.0,其中遇到了很多问题,电脑的系统以及相关配置都会在安装过程中受到影响,因此笔者就安装中的问题以及环境搭建来介绍一下. ...

  3. wince下sources\sources.cmn\Makefile.def的相关作用

    1:首先是Makefile.def: ---------------------------------------- 在所有驱动的makefile中有!INCLUDE $(_MAKEENVROOT) ...

  4. SD card技术了解并WINCE下SDHC驱动开发(updated)

    Suumary: 简单介绍了一下SD卡的历史和发展,同时结合MX31 ADS上的WINCE 下SDHC驱动更深入的了解该硬件的一些行为特点. 了解SD card SD是Secure Digital C ...

  5. WINCE下进程间通信(二)

    WINCE下进程间通信(二) 接着前面的文章<WINCE下进程间通信(一)>,现在介绍进程间通信的另一种方法. 三.管道(消息队列) WINCE并不支持类似于PC机上匿名管道.命名管道的通 ...

  6. WinCE下SQLCE数据库开发(VS,VB.net,VC++)

    WinCE下SQLCE数据库开发(VS,VB.net,VC++)   WinCE下SQLCE数据库开发 微软的SQL Server数据库由于其功能强大.方便使用,因此在很多行业都被广泛应用.基于智能设 ...

  7. WinCE下的串口通信开发(VS2005,VB.Net,VC++)

    WinCE下的串口通信开发(VS2005,VB.Net,VC++)   WinCE下的串口通信开发 一.利用Visual Basic 开发很简单,因为有现成的控件可以直接调用 以VS2005为例,首先 ...

  8. Windows Embedded CE 6.0开发环境的搭建(2)

    最近开始在学习嵌入式,在这里首先得安装Windows Embedded CE 6.0,其中遇到了很多问题,电脑的系统以及相关配置都会在安装过程中受到影响,因此笔者就安装中的问题以及环境搭建来介绍一下. ...

  9. WinCE下读取注册表获得SD路径

    WinCE下读取注册表获得SD路径 [要点]WinCE注册表中[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMemory\] 下键Folde ...

随机推荐

  1. 夺命雷公狗---node.js---15之加密

    node其实也给我们留下了密码的加密发送,不过一般都是用cmd5加密其实也是够了,但是sha1加密也要提下: /** * Created by leigood on 2016/8/31. */ var ...

  2. php导出word格式数据的代码

    <?php /** * 生成word文档的类 * by www.jbxue.com */ class word {          function start()     {         ...

  3. 人工智能深度学习Caffe框架介绍,优秀的深度学习架构

    人工智能深度学习Caffe框架介绍,优秀的深度学习架构 在深度学习领域,Caffe框架是人们无法绕过的一座山.这不仅是因为它无论在结构.性能上,还是在代码质量上,都称得上一款十分出色的开源框架.更重要 ...

  4. jeditable参数详解

    一.导入js文件 <script type="text/javascript" src="jquery-1.10.2.min.js"></sc ...

  5. printf,sprintf,vsprintf 区别【转】

    转自:http://blog.csdn.net/anye3000/article/details/6593551 有C语言写作历史的程序员往往特别喜欢printf 函数.即使可以使用更简单的命令(例如 ...

  6. PHP数组的一些常用函数

    [数组排序]sort()低到高,rsort()高到低.保持键值对应关系使用 asort()和arsort().对键排序ksort()和krsort().随机排序 shuffle(). [数组key相关 ...

  7. 《Head First设计模式》

    单件模式: 确保一个类只有一个实例,并提供一个全局访问点. 没有公开的构造函数,而采用一个公开的静态成员函数调用构造函数(使用该静态成员函数调用就是全局访问点,使用它可以在需要时才实例化对象),确保只 ...

  8. [算法][C]计算向量的角度

    C 语言里 double atan2(double y,double x) 返回的是原点至点(x,y)的方位角,即与 x 轴的夹角.也可以理解为复数 x+yi 的辐角.返回值的单位为弧度,取值范围为 ...

  9. 探索Win32系统之窗口类(转载)

    Window Classes in Win32 摘要 本文主要介绍win32系统里窗口类的运做和使用机制,探索一些细节问题,使win32窗口类的信息更加明朗化. 在本文中,"类", ...

  10. 2016年12月15日 星期四 --出埃及记 Exodus 21:10

    2016年12月15日 星期四 --出埃及记 Exodus 21:10 If he marries another woman, he must not deprive the first one o ...