在WINCE中基于ActiveSync的Socket通信 c#

发布于 2022-09-30 18:30:08 字数 5970 浏览 23 评论 0

转:poplau

在WINCE中基于ActiveSync的Socket通信 c#

一、序

之前做WINCE的项目,涉及到PC与PDA通信的时候,采用的是ActiveSync的通信方式,在PC上采用RAPI函数对PDA中的数据或文件进行控制,这种方式是单项的,与PDA中的程序基本无联系,在扩展性和功能性方面存在一些局限性。

采用Socket通信是一种不错的选择,但由于应用在特殊行业,不能使用WIFI模块和3G模块,PDA上没有分配IP地址,好像并不具备Socket通信的条件。

在查找了一些资料后发现ActiveSync通信其实是基于TCP的连接方式,既然是TCP,那么一定有地址和端口。

在PDA程序中运行:

  1. Dns.GetHostEntry(Dns.GetHostName()).AddressList[0].ToString();

复制代码发现了“192.168.55.101”这个地址。
运行:

  1. Dns.GetHostEntry(“PPP_PEER”).AddressList[0].ToString();

复制代码发现了“192.168.55.100”这个地址。

二、基于ActiveSync的Socket通信

当PDA与PC通过ActiveSync的方式连接后,PDA会得分配到192.168.55.101的IP地址,PC会分配到192.168.55.100的IP地址,值得注意的是PC上的这个IP地址是无法通过Ipconfig指令查找到的,也无法ping通,无法Bind,不算是一个真正意义上的IP地址。而且任何一台PDA通过ActiveSync连接后,地址都相同(PC 192.168.55.100,PDA 192.168.55.101)。

初步确定采用PC作为Socket Server端,PDA作为Socket Client端进行数据通信这种方式后(注1),就着手开始编写代码。
2.1 Socket Server端(PC服务器)

代码与普通Socket Server代码没什么两样,值得注意的是Bind的IP地址不能为192.168.55.100,也不能为该计算机的网络IP地址,而需要绑定“127.0.0.1”。

  1. IPEndPoint iep = new IPEndPoint(IPAddress.Parse(“127.0.0.1”), 10000);
  2. m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  3. m_Socket.Bind(iep);

复制代码2.2Socket Client端(PDA端 WINCE)

代码与普通Socket Client代码差不多,连接的地址设置为“192.168.55.100”,可采用这样的方式编写:

  1. string m_ServerIp = "";
  2. try
  3. {
  4.     m_ServerIp = Dns.GetHostEntry(“PPP_PEER”).AddressList[0].ToString();
  5. }catch {
  6.     m_ServerIp = "192.168.55.100";
  7. }
  8. IPAddress serverIp = IPAddress.Parse(m_ServerIp);
  9. int serverPort = 10000;
  10. IPEndPoint iep = new IPEndPoint(serverIp, serverPort);
  11. m_SocketConnection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  12. m_SocketConnection.Connect(iep);

复制代码另外值得注意的是Socket的Connected属性,在PC端的Socket Server服务关闭(Close)的情况下,PDA只要Connect后 Connected属性都会变成true。因此不能仅仅通过Connected属性来判断Socket是否连接正常,需要单独开一个线程,采用心跳包的方式进行检测。最好在Socket.Connect后执行一下Socket.Receive,如果成功则说明网络正常(注2),不成功说明网络断开。为防止Receive阻塞,PC服务端程序在与PDA连接后应立即发送一个短字节给客户端,让客户端接收。

三、Socket中涉及到的结构字节数组转换

Socket通信中涉及到很多结构与字节数组的转换,在WINDOW上运行正常的程序在WINCE中会报”不支持….”的异常。代码如下:

  1. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  2. public struct SocketMsg
  3. {
  4.         public SocketMsgType MsgId; //枚举类型
  5.         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
  6.         public string MsgDatetime;
  7.         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
  8.         public string MsgContent;
  9. }
  10. SocketMsg msg = new SocketMsg();
  11. Msg.MsgId = 0;
  12. Msg.MsgDatetime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
  13. Msg.MsgContent = "";
  14. private byte[] MsgStructToByte(SocketMsg msg)
  15. {
  16.      int size = Marshal.SizeOf(msg);
  17.      System.IntPtr ptr = Marshal.AllocHGlobal(size);
  18.      try
  19.      {
  20.           Marshal.StructureToPtr(msg, ptr, false);
  21.           byte[] ba = new byte[size];
  22.           Marshal.Copy(ptr, ba, 0, ba.Length);
  23.           return ba;
  24.       }
  25.       finally
  26.       {
  27.           Marshal.FreeHGlobal(ptr);
  28.       }
  29. }

复制代码以上代码在WINDOW下运行正常,但是在WINCE运行到StructureToPtr时报异常,异常显示不支持ByValTStr这种方式。为解决该问题,需要改变该结构定义。

  1. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  2. public struct SocketMsg
  3. {
  4.         public SocketMsgType MsgId; //枚举类型
  5.         [MarshalAs(UnmanagedType. ByValArray, SizeConst = 20)]
  6.         public byte[] MsgDatetime;//注3
  7.         [MarshalAs(UnmanagedType. ByValArray, SizeConst = 100)]
  8.         public byte[] MsgContent;
  9. }
  10. SocketMsg msg = new SocketMsg();
  11. msg.MsgId = 0;
  12. msg.MsgDatetime = Encoding.ASCII.GetBytes(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")+" ");
  13. msg.MsgContent = new byte[100];

复制代码需要说明的是 +" ",因为MsgDatetime数组定义为20字节,而”2011-03-31 -15:30:30”是19位,因此需要补一个空格凑足20位,StructureToPtr时就不会报异常了,同样道理在给MsgContent赋值的时候也应该注意该问题。

四、另外一些补充说明

OpenNETCF是一个很好的开发库,但是在WINCE中,由于一些DLL不存在,因此需要有选择的使用。例如因为没有Cellcore.dll这个文件(Windows mobile支持),在WINCE中无法使用OpenNETCF.Net Namespace中的ConnectionManager Class来管理网络连接状态。

附:

以上代码的环境为:

PC端:WIN2003,ActiveSync4.5,F2.0

PDA端:WINCE5.0,CF2.0

注1:Google里资料说PDA作为Socket Server ,PC作为Socket Client的好像无法实现,因此就没有进行测试,有兴趣的朋友可测试一下。

注2:不能用Socket.Send,测试发现在Socket Server服务关闭的情况下,Connect后Send有时也会成功

注3:在WINCE中 char默认为unicode16位,因此在定义结构体时最好采用byte。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文