确保Windows Mobile通过GPRS连接CMNET成功的办法(附源码)

【版   本】

1.0.0

【操作系统】

Windows Mobile 6.1

【作   者】

谢红伟·chrys ·chrys@163.com ·http://callgle.xicp.net

【开发日期】

2010-04-02 1:24

【文档日期】

2010-04-02 3:53

【说明】

用连接管理器API可以对Windows MobileGPRS连接进行管理,由程序发起连接GPRS请求完成连接的建立,但是有时候不那么幸运,Internet设置里多了一些其他无效的连接或者是复位后所有连接都丢失了,那我们应该主动创建自己的连接,然后实现联网。

【源代码下载】

 

http://www.pudn.com/downloads237/sourcecode/comm/windows_mobile/detail1109614.html

问题出现

三年前写过一篇文章《Windows Mobile中如何建立GPRS连接以便Socket能正常通信》(http://www.vckbase.com/document/viewdoc/?id=1803),该代码在我的一个项目中一直使用,可最近我的测试员殷慧和曹昌利告诉我说在以下这种情况下会导致GPRS连接CMNET时失败,手机上的连接配置如下图所示:

 

网络连接配置

【注意】这里多了一个“我的连接”,接入点是“cmwap”。

按理说,这些连接里已经有一个“cmnet”的了,应该可以连接到Internet的,我们用IE访问一下网站测试一下,结果令人费解,居然打不开网站,如下图:

 

IE访问百度网页失败

检查连接信息时发现原来系统默认连接到“我的连接”(cmwap)去了,所以无法访问普通的网站,只能访问wap网站,那是不是系统优先选择cmwap的接入点呢?我试了一下,即使我将“我的连接”的接入点有“cmwap”改成“abc”,系统照样优先选择这个错误的连接(因为世界上不存在“abc”这样的接入点),其实系统是自动选择最后一次创建的连接。我将连接列表里的“自动选择”改为手动指定到“cmnet”,如下图:

 

手动指定

手动指定后可以连接到Internet。难道需要我们最敬爱的用户来做如此高难度的事情吗?什么?不难?是的,对于我们程序员来说,将连接从“自动选择”改为手动指定的确没什么难度,但对于一个连电脑开机按钮都找不到的用户来说,那可比一口气吃下十个包子还要难啊!~O(_)O~

我同事有一台香港买的繁体版HTC S1高档货,复位以后居然一个连接都找不到,当然也不能访问网络了。看来建立我们自己的连接是势在必行了。

想办法解决它

我们是程序员,哪怕是一点小小的问题,只要是为用户提供了方便,减少了用户的困扰,我们就为此而努力,这是我们的人生真谛!

经过测试发现,我只要将手机里所有的连接都删掉,然后建立一个我们自己想要的连接,每次都可以成功,现在我们要做的就是如何删除系统中原有连接,我们这里要用到一个特殊的函数,我们称之为“万能”函数,函数名为DMProcessConfigXML()”,该函数以XML方式向系统提交修改系统配置的请求,这些请求是多方面的,比如:可以用来发送电子邮件,还可以用来建立Wi-Fi连接、卸载应用程序等。我们这里要利用它来删除系统连接,我们先建立一个删除单个连接的函数,代码如下:

 

BOOL CConnectManager::DeleteOneGPRSConn ( LPCTSTR lpszConnName )

{

       if ( !lpszConnName || lstrlen(lpszConnName) < 1 )

              return FALSE;

 

       CString csWXMLin;

 

       csWXMLin = _T("<wap-provisioningdoc>");

       csWXMLin += _T("<characteristic type=/"CM_GPRSEntries/">");

       csWXMLin += _T("<nocharacteristic type=/"") + CString(lpszConnName) + _T("/"/>");

       csWXMLin += _T("</characteristic>");

       csWXMLin += _T("</wap-provisioningdoc>");

       return DMProcessConfigXML ( CFGFLAG_PROCESS, csWXMLin );

 

 

       return TRUE;

}

 

然后用函数“ConnMgrQueryDetailedStatus()”枚举系统中所有的连接名称,再循环调用“DeleteOneGPRSConn”函数,将所有连接都删掉。

删掉以后接下来应该创建一个“cmnet”的接入点,代码如下:

BOOL CConnectManager::CreateGPRSConn ( LPCTSTR lpszConnName, LPCTSTR lpszAPN )

{

       if ( !lpszConnName || lstrlen(lpszConnName) < 1 )

              return FALSE;

       if ( !lpszAPN || lstrlen(lpszAPN) < 1 )

              return FALSE;

 

       CString csWXMLin;

       csWXMLin = _T("<wap-provisioningdoc>");

       csWXMLin += _T("<characteristic type=/"CM_GPRSEntries/">");

       csWXMLin += _T("<characteristic type=/"") + CString(lpszConnName) + _T("/">");

       csWXMLin += _T("<parm name=/"DestId/" value=/"{436EF144-B4FB-4863-A041-8F905A62C572}/" />");

       csWXMLin += _T("<characteristic type=/"DevSpecificCellular/">");

       csWXMLin += _T("<parm name=/"BearerInfoValid/" value=/"1/" />");

       csWXMLin += _T("<parm name=/"GPRSInfoValid/" value=/"1/" />");

       csWXMLin += _T("<parm name=/"GPRSInfoProtocolType/" value=/"2/" />");

       csWXMLin += _T("<parm name=/"GPRSInfoL2ProtocolType/" value=/"PPP/" />");

       csWXMLin += _T("<parm name=/"GPRSInfoAccessPointName/" value=/"") + CString(lpszAPN) + _T("/" />");

       csWXMLin += _T("<parm name=/"GPRSInfoAddress/" value=/"/" />");

       csWXMLin += _T("<parm name=/"GPRSInfoDataCompression/" value=/"1/" />");

       csWXMLin += _T("<parm name=/"GPRSInfoHeaderCompression/" value=/"1/" />");

       csWXMLin += _T("<parm name=/"GPRSInfoParameters/" value=/"/" />");

       csWXMLin += _T("</characteristic>");

       csWXMLin += _T("</characteristic>");

       csWXMLin += _T("</characteristic>");

       csWXMLin += _T("</wap-provisioningdoc>");

 

       return DMProcessConfigXML ( CFGFLAG_PROCESS, csWXMLin );

}

 

有了这两个函数,那我们建立连接Internet之前先删除再创建,如下代码:

 

BOOL CConnectManager::CreateNewCmnetConn ()

{

       DeleteAllGPRSConn ( NET_CONN_NAME );

       if ( !CreateGPRSConn ( NET_CONN_NAME, _T("cmnet") ) )

              return FALSE;

       return TRUE;

}

 

现在GPRS的连接已经准备就绪,我们只需要调用函数“ConnMgrEstablishConnectionSync()”来建立连接即可,系统会自动选择我们创建的连接。

 

BOOL CConnectManager::ConnectToInternet ()

{

       // 尝试用IID_DestNetInternet 来连接

       GUID guidDestNetInternet = {0};

       guidDestNetInternet.Data1 = 0x436ef144;

       guidDestNetInternet.Data2 = 0xb4fb;

       guidDestNetInternet.Data3 = 0x4863;

       guidDestNetInternet.Data4[0] = 0xa0;

       guidDestNetInternet.Data4[1] = 0x41;

       guidDestNetInternet.Data4[2] = 0x8f;

       guidDestNetInternet.Data4[3] = 0x90;

       guidDestNetInternet.Data4[4] = 0x5a;

       guidDestNetInternet.Data4[5] = 0x62;

       guidDestNetInternet.Data4[6] = 0xc5;

       guidDestNetInternet.Data4[7] = 0x72;

 

       if ( EstablishConnection ( guidDestNetInternet ) )

       {

              return TRUE;

       }

 

       // 映射URL

       CString csDesc;

       GUID guidNetworkObject = {0};

       int nIndex = MapURLAndGUID(_T("www.163.com"), guidNetworkObject, &csDesc );

       if ( nIndex < 0 ) return FALSE;

 

       // 连接映射URL得到的连接对象

       if ( EstablishConnection ( guidNetworkObject ) )

       {

              return TRUE;

       }

 

       return FALSE;

}

 

本文所附带的源代码,是一个Demo程序,实现了自动连接GPRS,且用Socket连接百度网站以检查我们是否真的能建立连接,如下图:

 

连接百度成功

 

被程序处理后的系统连接列表如下图所示:

 

程序创建的连接

 

上图中的“szxys.chrys”为程序自动创建的连接,系统默认会使用该连接,GPRS连接cmnet成功!

结束语

其实我们还可以用RASRemote Access Service,即“远程访问服务”)系列API来管理我们的连接,例如用RasDial()函数就可以进行拨号,但我测试发现,这些函数和连接管理器提供的API还是有冲突的,比如用RasDial()拨号成功了,可连接图标不显示,界面上看不出来当前是否已经联网,但又可以访问网络;再比如我用IE连接到cmwap了,再用RasDial()拨号会导致程序挂住。所以建议还是使用连接管理器API来管理我们的GPRS连接会比较安全。

该程序在中国大陆使用中国移动的SIM卡使用没问题,如果在国外,或者是使用联通的卡,接入点不尽相同,需要修改里面的参数。

知识就是力量,知识共享将具有推动时代进步的力量。希望我能为中国的软件行业尽一份薄力。

你可以任意修改复制本代码,但请保留版权信息文字不要修改。

由于水平有限,错误再所难免,请知情者原谅并告知,多谢!

 

·谢红

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值