点击打开链接

背景

在开发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. 夺命雷公狗---TP商城----TP之样式和特效以及图片引入---2

    ---恢复内容开始--- 刚才见到笑脸了,那么下一步就到我们的shop目录下创建一个Admin的目录了,然后将Home目录里面的东西全部都拉进去即可 然后我们回到shop\Home\View目录下创建 ...

  2. PAT乙级 1008. 数组元素循环右移问题 (20)

    1008. 数组元素循环右移问题 (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 一个数组A中存有N(N>0)个整数,在不允 ...

  3. 修改linux下mysql目录权限

    1.进入当前目录:例cd /srun3/mysql 2.修改权用户限 chown -R mysql ipt_authd_remote(表示给ipt_authd_remotemysql权限) 3.修改用 ...

  4. remoting方式

    1. WebService跨平台,跨防火墙,但是很抱歉,基于xml速度慢2. RMI(java)/Remoting(.net)平台相关,基于二进制序列化,速度快.3.dcom(com+)spring提 ...

  5. dota BP练习工具开发:一个C/S多用户程序

    首发:个人博客,更新&纠错&回复 客户端采用C#开发,服务器使用java开发,通信方式为socket. 1.首先决定交互协议 客户端指令协议: getgames:要求服务端发送game ...

  6. struts2 笔记01 登录、常用配置参数、Action访问Servlet API 和设置Action中对象的值、命名空间和乱码处理、Action中包含多个方法如何调用

    Struts2登录 1. 需要注意:Struts2需要运行在JRE1.5及以上版本 2. 在web.xml配置文件中,配置StrutsPrepareAndExecuteFilter或FilterDis ...

  7. linux上操作mysql数据库

    sudo /etc/init.d/mysql start启动mysql netstat -lntup|grep 3306查看端口3306 grant all privileges on *.* to ...

  8. MySql的Delete、Truncate、Drop分析

    MySql的Delete.Truncate.Drop分析 相同点: truncate 和不带 where 子句的 delete,以及 drop 都会删除表内的数据 不同点 1. truncate 和 ...

  9. 160926、Java-SpringMVC统一异常处理

    从零开始学 Java - Spring MVC 统一异常处理 看到 Exception 这个单词都心慌 如果有一天你发现好久没有看到Exception这个单词了,那你会不会想念她?我是不会的.她如女孩 ...

  10. linux中Iptables限制同一IP连接数防CC/DDOS攻击方法

    1.限制与80端口连接的IP最大连接数为10,可自定义修改.  代码如下 复制代码 iptables -I INPUT -p tcp --dport 80 -m connlimit --connlim ...