点击打开链接

背景

在开发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. 夺命雷公狗---Thinkphp----7之栏目配合Model的增删改查

    我们首先来写一个查: public function lists(){ $type = M('Type')->select(); $this -> assign('type',$type) ...

  2. ThinkPHP讲解(四)——视图

    本次讲解主要以<ThinkPHP开发手册>中“模板”一章中讲解为主 在MainController.class.php中新建一个操作方法Test() namespace Home\Cont ...

  3. [php] How to debug PHP in the terminal

    Here I use Netbeans, xdebug to debug the PHP in the terminal of Ubuntu. 1. you have to install the x ...

  4. [CrunchBang]Linux系统下必要的中文字体

    sudo apt-get install ttf-droid ttf-wqy-zenhei xfonts-wqy ttf-wqy-microhei ttf-arphic-ukai ttf-arphic ...

  5. 「linux」win+linux 双系统 默认启动项 的修改

    修改/etc/default/grub文件,其中的GRUB_DEFAULT表示默认启动项: sudo gedit /etc/default/grub 注意:启动项是从0开始计数. 要使修改生效需要运行 ...

  6. Android SDK Manager更新报错

    错误log: Fetching https://dl-ssl.google.com/android/repository/addons_list-.xml Fetched Add-ons List s ...

  7. Hadoop之TaskAttemptContext类和TaskAttemptID类

    先来看看TaskAttemptContext的类图 : Figure1:TaskAttemptContext类图 用户向Hadoop提交Job(作业),Job在JobTracker对象的控制下执行.J ...

  8. java笔试题: ——将e:/source文件夹下的文件打个zip包后拷贝到f:/文件夹下面

    将e:/source文件夹下的文件打个zip包后拷贝到f:/文件夹下面 import java.io.*; import java.util.zip.ZipEntry; import java.uti ...

  9. overflow的劲爆知识点

    1.属性 visible(默认) hidden(此处是隐藏不是裁剪) scroll(滚动条) auto(智能路线 当超出范围时则出现滚动条) inherit 不常用  存在兼容性问题 2.进入CSS3 ...

  10. php的ssh2扩展安装

    折腾半天,结论如下: 1.先需要openssl 用which openssl看是否已安装 2.然后libssh2 用rpm -ql libssh2查看 3.下载源码的shh2x.x.x.tgz的包 4 ...