现在的位置: 首页 > 综合 > 正文

GPRS下开发SOCKET程序入门

2013年09月20日 ⁄ 综合 ⁄ 共 8948字 ⁄ 字号 评论关闭

先介绍下GPRS,

要使用GPRS的函数之前,先导入库

#include <Connmgr.h>
#pragma comment ( lib, "Cellcore.lib" )

 

 

介绍下connection manager的一些函数:

1.       客户端建立GPRS连接 API

客户端开发采用 EVC4.0进行开发,主要讲解的类库为Connection Manager 系列API,客户端在进行GPRS拨号连接时将使用下文所介绍的API

Connection Manager(本人译为 连接管理器,此对象为一系列API的集合) 系列API的主要目的是为了集中管理基于Windows Mobile系列的设备网络连接的建立与维护。移动应用程序使用 连接管理器API去建立或规划一个网络连接,而连接管理器则掌控连接过程中的所有状态信息.应用程序在要发起一个连接(比如Internet),只要简单的告知连接管理器就OK了。

当一个应用程序发起一个网络连接的请求时,连接管理器首先从连接服务提供商(CSPS)处获取所有可能的连接信息,然后连接管理器会从这一系列连接信息中根据开销,延迟、带宽等因素来选择一个最佳的连接,最后连接管理器将被请求的连接排入队列,然后在一个适合的时间使用CSPS来建立连接。    

API函数】:

a)       ConnMgrApiReadyEvent()函数
函数原型:HANDLE WINAPI ConnMgrApiReadyEvent();
利用此函数来我们可以返回一个连接事件的句柄 ,注意在的得到句柄后要记得及时释放

b)       ConnMgrConnectionStatus()函数
函数原型:
HRESULT WINAPI ConnMgrConnectionStatus(HANDLE hConnection,DWORD * pdwStatus );
利用此函数的返回值pdwStatus,我们可以得到很多的关于连接的信息,例如如果我们连接成功将返回CONNMGR_STATUS_CONNECTED,断开连接将返回CONNMGR_STATUS_DISCONNECTED,他的返回状态信息非常丰富,有14中之多,完全可以满足我们的应用需要;

c)        ConnMgrEnumDestinations()函数
函数原型:
HRESULT WINAPI ConnMgrEnumDestinations(int nIndex,CONNMGR_DESTINATION_INFO * pDestInfo )

一般我们的PDA在连接GPRS时都有好几个连接,利用此函数我们可以枚举出所有可用的连接,然后再对挑选的连接进行筛选得到一个最佳连接

接下来讲两个很重要的函数,我们将利用两个函数中的一个来发起连接,他们是:

d)       ConnMgrEstablishConnection()ConnMgrEstablishConnectionSync()函数,这两个函数一个用于发起一个异步连接请求,一个用于同步请求,使用异步连接请求我们可以在发起连接后立即返回,而使用同步请求客户端将一直被阻塞知道函数返回确认连接,关于异步和同步我就不再叙述;
它们的原型依次为:
HRESULT WINAPI ConnMgrEstablishConnection( CONNMGR_CONNECTIONINFO * pConnInfo, HANDLE * phConnection );
HRESULT WINAPI ConnMgrEstablishConnectionSync(   CONNMGR_CONNECTIONINFO * pConnInfo, HANDLE * phConnection,    DWORD dwTimeout, DWORD * pdwStatus );
     
可以看到两个函数的第一个参数都为一个CONNMGR_CONNECTIONINFO对象,此对象为一个结构体,它保存了客户端发起连接请求的一系列信息,因此,在我们调用此函数时必须构造一个该对象,然后将其作为参数传入连接函数中。这里很有必要讲一下该结构体,该结构体的原型如下:
typedef struct _CONNMGR_CONNECTIONINFO
{
     DWORD cbSize;   DWORD dwParams;DWORD dwFlags;

           DWORD dwPriority;BOOL bExclusive;BOOL bDisabled;GUID guidDestNet;

           HWND hWnd;  UINT uMsg; LPARAM lParam;ULONG ulMaxCost;  ULONG ulMinRcvBw;  
      ULONG ulMaxConnLatency;

        } CONNMGR_CONNECTIONINFO;
其中参数dwFlags用于指定我们的接入点,比如我们常说的CMNERCMWAP,而参数GUID则标志了我们对应于每个接入点的全球唯一标志符,关于如何得到或者查看GUID,我们可以在“/Program Files/Windows CE Tools/wce420/POCKET PC 2003/Include/Armv4”目录下查看connmgr.h文件,里面包含了各个接入点的GUID,例如:

CMNET 为:(0x436ef144, 0xb4fb, 0x4863, 0xa0, 0x41, 0x8f, 0x90, 0x5a, 0x62, 0xc5, 0x72)

 CMWAP为:0x7022e968, 0x5a97, 0x4051, 0xbc, 0x1c, 0xc5, 0x78, 0xe2, 0xfb, 0xa5, 0xd9

如果想更进一步了解,我们还可以通过查看注册表方式来查看PDA上连接管理器的相关连接信息,在PPC 2003中注册表路径为:

[HKEY_LOCAL_MACHINE/Comm/ConnMgr],如下图所示:

register

现在开始实践下

手机开通GPRS以后,我们的socket 程序还不能直接建立网络连接,需要用连接管理器来获取当前可用连接,并自动选择一个最佳的连接途径,然后启用这个连接,在连接启动成功以后再用socket 进行网络连接方可正常进行。大概GPRS拨号和连接过程就是在这里自动进行的吧。源代码中封装了一个连接管理的类和测试代码,可以清楚地看到Windows Mobile 在socket 编程之前到底需要做什么样的操作。

首先需要枚举当前可用的连接

接下来找到“Internet”这个连接,可用远程URL映射的方式来完成,这样可以让系统自动选取一个最好的连接。

 

以下代码是用来启用指定编号的连接

 

 

为了确保连接是否真正可用,需要检测连接状态,在规定的时间内如果未取得“连接成功”的状态,则认为连接未能正常启用,可能需要配置手机的连接管理器界面

 

 

至此,我们的连接启用工作已经做完了,我们可以用我们熟悉的 socket 来编写网络通信程序了。下面是一个测试 socket 测试网络连接是否能正常建立的例子:

 

具体的文章在:http://www.vckbase.com/document/viewdoc/?id=1803

 

 

 

 

 

 

在国际上,通常只有一种GPRS接入方式,在中国有CMWAP和CMNET两个接入点,前者是为手机WAP上网而设立的,后者则主要是为PC、笔记本电脑、PDA等利用GPRS上网服务。它们在实现方式上并没有任何差别,但因为定位不同,所以和CMNET相比,CMWAP便有了部分限制,资费上也存在差别。
下面这段代码连接CMNET.
//连接GPRS
 DWORD dwStatus;// = 0;
 HANDLE hConnection=NULL;
 CONNMGR_CONNECTIONINFO sConInfo;
 memset(&sConInfo, 0 ,sizeof(CONNMGR_CONNECTIONINFO));
 sConInfo.cbSize = sizeof(CONNMGR_CONNECTIONINFO);
 sConInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET;
 sConInfo.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;
 sConInfo.dwFlags = CONNMGR_FLAG_PROXY_HTTP|CONNMGR_FLAG_PROXY_WAP|CONNMGR_FLAG_PROXY_SOCKS4|CONNMGR_FLAG_PROXY_SOCKS5;
 sConInfo.bExclusive = FALSE;
 sConInfo.bDisabled = FALSE;
 sConInfo.guidDestNet = IID_DestNetInternet; //IID_DestNetWAP
 sConInfo.hWnd = 0;
 sConInfo.uMsg = 0;
 if (FAILED(ConnMgrEstablishConnectionSync(&sConInfo, &hConnection, 60000, &dwStatus))) ;
目前,移动的WAP网关对外只提供HTTP代理协议(80和8080端口)和WAP网关协议(9201端口),彩信还有单独配置接入点是因为彩信服务需要连接专用的服务器。所以把上面那段代码中的IID_DestNetInternet换成IID_DestNetWAP,实际中是不能连通GPRS的。
if (m_hConnection)
 {
  ConnMgrReleaseConnection(m_hConnection, FALSE);
  m_hConnection = NULL;
 }
CStringArray StrAry;
 CONNMGR_DESTINATION_INFO networkDestInfo = {0};
 // 得到网络列表
 for ( DWORD dwEnumIndex=0; ; dwEnumIndex++ )
 {
  memset ( &networkDestInfo, 0, sizeof(CONNMGR_DESTINATION_INFO) );
  if ( ConnMgrEnumDestinations ( dwEnumIndex, &networkDestInfo ) == E_FAIL )
  {
   break;
  }
  StrAry.Add ( networkDestInfo.szDescription );
 }

 int Index =0;
 //查找“WAP”的索引
 for (int i = 0; i < StrAry.GetCount(); ++i)
 {
  if (StrAry[i] == L"WAP")
  {
   Index = i;
   break;
  }
 }
 // 得到正确的连接信息
 CONNMGR_DESTINATION_INFO DestInfo = {0};
 HRESULT hResult = ConnMgrEnumDestinations(Index, &DestInfo);
 BOOL bRet = FALSE;
 if(SUCCEEDED(hResult))
 {
  // 初始化连接结构
  CONNMGR_CONNECTIONINFO ConnInfo;

  ZeroMemory(&ConnInfo, sizeof(ConnInfo));
  ConnInfo.cbSize = sizeof(ConnInfo);
  ConnInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET;
  ConnInfo.dwFlags = CONNMGR_FLAG_PROXY_HTTP | CONNMGR_FLAG_PROXY_WAP | CONNMGR_FLAG_PROXY_SOCKS4 | CONNMGR_FLAG_PROXY_SOCKS5;
  ConnInfo.dwPriority = CONNMGR_PRIORITY_HIPRIBKGND;//CONNMGR_PRIORITY_USERINTERACTIVE;
  ConnInfo.guidDestNet = DestInfo.guid;
  ConnInfo.bExclusive = FALSE;
  ConnInfo.bDisabled = FALSE;

  DWORD dwStatus = 0;
  hResult = ConnMgrEstablishConnectionSync(&ConnInfo, &m_hConnection, 100*1000, &dwStatus );
//   if(FAILED(hResult))
//   {
//    MessageBox(NULL,L"连接失败",L"错误信息",MB_OK);
//    m_hConnection = NULL;
//   }
//   else
//   {
//    MessageBox(NULL,L"连接成功",L"错误信息",MB_OK);
//    return TRUE;
//   }
 }
上面两段代码仅限于连接移动的GPRS。注意:m_hConnection最好设成全局变量,这样程序退出时关闭GPRS

所需的头文件和lib库
#include <connmgr.h>
#include <connmgr_proxy.h>
#pragma comment( lib, "cellcore.lib" )

 

 

 

 

------------------------------------------------------------------------------

模拟GPRS:

在上面的文章已经说到怎么模拟短信和打电话,但是我们发现在NETWORK那一项中的

GPRS依然是DISCONNNECT,这是为什么呢,最后我尝试了很多方法才成功的模拟出了在

模拟器上连接GPRS,方法如下:

首先:当你模拟器插入底座时,同步时,最后一步问你要不要什么MMS,什么连接的,在

这里选择不连接就行了

接着:进入手机,“开始-》设置-》连接-》GPRS”,在里面我们新建两个GPRS连接,如下

GPRS                                        GPRS INTERNET

连接到:WAP网络                               internet

访问点:CMWAP                                  cmnet

用户名: 

密码:

主DNS:0.0.0.0                                  0.0.0.0

辅助DNS:0.0.0.0                                0.0.0.0

IP地址:10.0.0.172                            10.0.0.172

最后,我们打开IE,输入网址连接,发现在CELLULAR EMULATOR下面的GPRS已经变为CONNECT了,

可以测试我们做的GPRS程序了!

当然还有个地方有问题,就是不能访问网页,SO,解决中

 

 

 

destNet

 

在这里里面有DestId一项,就对应着我们久违的GUID

e)       ConnMgrReleaseConnection函数
我们在上一步中建立连接后我们将得到一个连接句柄,在重新开始一个新的连接或者断开连接都要调用此函数来释放掉之前创建的连接,它的原型为:
HRESULT WINAPI ConnMgrReleaseConnection( HANDLE hConnection,BOOL bCache );

【连接管理API大致使用步骤】:

首先我们利用ConnMgrApiReadyEvent()函数来确认是否有可用连接,如果有可用连接我们则利用ConnMgrEnumDestinations()函数枚举所有可用连接,然后遍历所有连接调用我们的同步或异步连接方法ConnMgrEstablishConnectionSync()ConnMgrEstablishConnection()来发起连接,一旦连接成功后我们就可以进行我们伟大的下一步了,就是和我们的服务器进行通信。

在Destinations一项中就对应我们所有可用的网络连接,这个跟用ConnMgrEnumDestinations()方法得到的是一样的效果,在默认Internet设置中我们将看到CMNET的GUID,如下所示:

抱歉!评论已关闭.