点击打开链接

背景

在开发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. SQL—— 事务

    SQL 事务: 1.  定义: 事务是作为单个逻辑单元执行的一系列操作. 多个操作作为一个整体向系统提交,要么执行.要么都不执行,事务是一个不可分割的工作逻辑单元.这特别适用于多用户同时操作的数据通信 ...

  2. OpenGL笔试题

    简述FrameBuffer,RenderBuffer,Depth Buffer,Framebuffer attachment,Stencil buffer的关系 简述利用OpenGL执行图像叠加(大P ...

  3. python 三元运算符

    print (1==2) and 12 or 4 b=12 if 1==2 else 4print(b)

  4. 记录下标准网线水晶头的做法 100m/1G

    注意, 网线分平行线(也叫直连线)和交叉线.  用法见下图 .也就是相同层内用交叉线, 不同层用平行线.  所以两台电脑,两台非级联并行的路由才用交叉线,一般我们都用平行线即可. 千兆网和百兆网不同: ...

  5. protocolbuffe

    protocolbuffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台.google 提供了多种语言的实现:java.c#.c++.go 和 python,每一种实 ...

  6. 161020、web调试工具fiddler介绍及使用

    简介: Fiddler是一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的"进出"Fiddler的数据(指cookie,ht ...

  7. 安装使用RESTful 框架SLIM方法

    相关框架: http://www.golaravel.com 是一个PHP框架,内置名为LUMEN的RESTful API框架,有中文文档, http://lumen.golaravel.com/do ...

  8. codeigniter中base_url和site_url

    首先在网站中使用如下的语句: site_url(‘manage/articleAdd’): 1 <?php echo site_url('manage/articleAdd');?> ba ...

  9. Codeforces 741B:Arpa's weak amphitheater and Mehrdad's valuable Hoses(01背包+并查集)

    http://codeforces.com/contest/741/problem/B 题意:有 n 个人,每个人有一个花费 w[i] 和价值 b[i],给出 m 条边,代表第 i 和 j 个人是一个 ...

  10. hdwiki 软件包结构

    HDWiki软件包结构转载自http://www.chinabaike.com/z/shenghuo/pc/2011/0414/814308.html           根目录下的PHP文件     ...