Windows Mobile, WinCe使用 .NET Compact Framework 进行3G和RAS应用的开发

在.NET Compact Framework下开发3G应用可以有两个options,1:AT command, 2:RAS。其实RAS最终也是通过AT command来管理3G设备,RAS屏蔽了技术细节,很方便地建立TCP/IP based 的网络连接,所以推荐使用RAS,WinCE本身提供了native API可以直接操作RAS,管理3G设备及其连接。与此同时RAS也支持有线电话拨号,GPRS等应用。

RAS简介

Overview of RAS,MSDN

RAS的详细介绍见 Overview of RAS

由于.NET Compact Framework 不直接提供RAS组件,因此只能通过native invoke来使用RAS。

RAS的native调用函数,事件及结构见 RAS Reference

关键的RAS native调用

 

        [DllImport("coredll.dll", CharSet = CharSet.Auto)]
        
private static extern Int32 RasGetEntryDialParams(string lpszPhoneBook,
        
byte[] lpRasDialParams,
        
out UInt32 lpfPassword);

        [DllImport(
"coredll.dll", CharSet = CharSet.Auto)]
        
private static extern int RasDial(IntPtr pDialExtensions,
                                                   
string pPhonebook,
                          
byte[] pRasDialParam,
                          
uint pNotifierType,
                          IntPtr pHwnd,
                          
ref int pRasConn);

        [DllImport(
"coredll.dll", CharSet = CharSet.Auto)]
        
private static extern int RasHangUp(int pSession);

        [DllImport(
"coredll.dll", CharSet = CharSet.Auto)]
        
private static extern uint RasGetConnectStatus(int pSession,
                                                                        
byte[] lpRasConnStatus);

RasGetEntryDialParams 取得原先配置的连接项,可以在手工新建连接或者修改注册表建立连接项(Connection Entry)。这个函数的关键作用是从连接项取出配置好的拨号密码。
RasDial 拨号到电信运营商的网络上。
RasHangUp 挂断连接。
RasGetConnectStatus 取当前的连接状态。

 

RAS 事件

在调用RasDial 时,如果uint pNotifierType传递0xFFFFFFFF,那么IntPtr pHwnd可以注册一个事件接受的Handler。当连接状态发生改变时,windows会把相应的事件发送给这个handler,这样我们可以接收这些事件,把之变成delegate来通知clients。这样就实现了一个Observer模式,client可以通过订阅来实时得到连接状态的变更状况。

要把windows event变成C#的delegate,要继承MessageWindow class,然后override  WndProc(ref Message pMsg),同时定义C#的delegate和event把windows事件变成delegate提供给client订阅。

 

public class RasManager : MessageWindow
    {
        
public delegate void NotifyEvent();
        
public event NotifyEvent OnConnectedEvent;
        
public event NotifyEvent OnDisconnectedEvent;

        
protected override void WndProc(ref Message pMsg)
        {
            
if (pMsg.Msg == WM_RASDIALEVENT)
            {
                
switch ((int)pMsg.WParam)
                {
                    
case (int)RASCONNSTATE.RASCS_OpenPort:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_PortOpened:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_ConnectDevice:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_DeviceConnected:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_AllDevicesConnected:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_Authenticate:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_AuthNotify:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_AuthRetry:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_AuthCallback:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_AuthChangePassword:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_AuthProject:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_AuthLinkSpeed:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_AuthAck:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_ReAuthenticate:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_Authenticated:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_PrepareForCallback:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_WaitForModemReset:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_WaitForCallback:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_Projected:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_Interactive:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_RetryAuthentication:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_CallbackSetByCaller:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_PasswordExpired:
                        {
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_Connected:
                        {
                            OnConnected();
                            
break;
                        }
                    
case (int)RASCONNSTATE.RASCS_Disconnected:
                        {
                            OnDisconnected();
                            
break;
                        }
                    
default:
                        {
                            
break;
                        }
                }
            }
            
base.WndProc(ref pMsg);
        }

RASCS_Disconnected windows 事件转换成OnConnected C# event, 而RASCS_Disconnected windows 事件转换成OnDisconnectedC# event

 

Client 的调用

事件注册可以放在Client 的Constructor上执行
RasManager.Instance.OnConnectedEvent +=
  new RasManager.NotifyEvent(Form1_OnConnectedEvent);
RasManager.Instance.OnDisconnectedEvent 
+=
  new
 RasManager.NotifyEvent(Form1_OnDisconnectedEvent); 

 

连接3G网络
RasManager.Instance.DialUp("3G Connection"nullnull);

 

断开连接
RasManager.Instance.HangUp();

 

查询连接状态

 

RasManager.RASCONNSTATE rasConnState =
  (RasManager.RASCONNSTATE) RasManager.Instance.GetStatus();

 

这个类同样可以使用于GPRS里面。

 

作者:Jake LinJake's Blog on 博客园
出处:http://procoder.cnblogs.com

作品Jake Lin创作,采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。 任何转载必须保留完整文章,在显要地方显示署名以及原文链接。如您有任何疑问或者授权方面的协商,请给我留言
posted @ 2009-01-06 11:30 Jake Lin 阅读(6151) 评论(13) 编辑 收藏

 回复 引用 查看   
#1楼 2009-01-06 09:39 JustDI      
有速度,这3G还没正式推出来呢
 回复 引用 查看   
#2楼[楼主] 2009-01-06 09:50 Jake Lin      
--引用--------------------------------------------------
JustDI: 有速度,这3G还没正式推出来呢
--------------------------------------------------------
已经在用了,这里用wcdma,否则老板也不会让我做。

 回复 引用 查看   
#3楼 2009-01-06 10:32 施炯      
呵呵 支持楼主
是不是已经在用多普达的3G的机子调试了?
期待下一篇

 回复 引用 查看   
#4楼[楼主] 2009-01-06 11:29 Jake Lin      
--引用--------------------------------------------------
施炯: 呵呵 支持楼主
是不是已经在用多普达的3G的机子调试了?
期待下一篇
--------------------------------------------------------
我用的是工业modem,不是手机。然后用wince设备连接该modem进行测试的。

 回复 引用 查看   
#5楼 2009-01-06 13:31 巫云      
学习一下,周末要入一部多普达D9000。
 回复 引用   
#6楼 2009-01-06 16:00 钻石机用户[未注册用户]
D9000的内存是64MB的,太小了。
 回复 引用   
#7楼 2009-04-28 20:21 beginner[未注册用户]
你好,想请问一下,at指令模式和ras两种工作模式能不能混合使用,有时候使用ras拨号上网会很方便,但是有时候使用at指令查询一些gsm信号会比较方便,所以请问能不能一起使用? 谢谢
 回复 引用 查看   
#8楼[楼主] 2009-04-30 06:50 Jake.NET      
@beginner
不好意思,我没有试过,关键看那个端口是不是独占的,ras最终也是翻译成AT指令,你中途插入些指令是没有问题的,但是要看那个发送指令的端口你能不能打开。

 回复 引用   
#9楼 2009-05-15 17:38 awinds[未注册用户]
有没有RasManager这个的代码,能不能发送一份到邮箱。谢谢
 回复 引用 查看   
#10楼[楼主] 2009-05-17 19:00 Jake.NET      
 回复 引用 查看   
#11楼 2010-10-18 23:12 so_zhou      
感谢楼主的奉献精神,在你们使用了一年之后,我也开始使用了,不止楼主能否辛苦一下,发送一份代码到我邮箱,上面这个地址我打不开。
谢谢
E_mail:so_zhou@qq.com

 回复 引用 查看   
#12楼[楼主] 2010-10-19 05:44 Jake Lin      
 回复 引用 查看   
#13楼 2011-10-19 15:29 雨夜骑士      
楼主,这两个连接我都打不开,能不能给我发一份,563182423@qq.com