科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件使用C#来开发.NET CF 蓝牙通信模块

使用C#来开发.NET CF 蓝牙通信模块

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在Windows Mobile软件开发中.Net正扮演着日益重要的角色,我们已经可以看到很多用.Net CF开发的软件,这些软件涉及到了日常应用的方方面面。

作者:I-soft 来源:CSDN 2007年11月18日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
由于是针对蓝牙作的开发,所以我们要查看一下这些参数应该是哪些值。Windows CE 4.2的SDK中说,蓝牙开发时,struct LPWSAQUERYSET中的如下成员应当为这些值:

以下是引用片段:
The dwSize member must be sizeof(WSAQUERYSET).
  The lpBlob member (itself a pointer to a BLOB structure) is optional, but if used, the device inquire parameters valid for LUP_FLUSHCACHE are the following:
  The cbSize member of the BLOB structure must be sizeof(BTH_QUERY_DEVICE).
  The pBlobData member is a pointer to a BTH_QUERY_DEVICE structure, for which the LAP member is the Bluetooth inquiry access code, and the length member is the length of the inquiry, in seconds.
  The dwNameSpace member must be NS_BTH.
  All other WSAQUERYSET members are ignored.

  具体什么意思各位可以自己去理解,我想比我翻译出来要好些,毕竟我英语很差的。根据以上要求,我们这样装配pQuerySet:

以下是引用片段:
byte[] buffer1 = new byte[0x400];
  BitConverter.GetBytes(60).CopyTo(buffer1, 0);
  GCHandle handle1 = GCHandle.Alloc(blob1.ToByteArray(), GCHandleType.Pinned);
  IntPtr ptr1 = handle1.AddrOfPinnedObject();
  BitConverter.GetBytes((int) (ptr1.ToInt32() + 4)).CopyTo(buffer1, 0x38);

  另外的两个API也照类似方法调用即可。

  在调用了WSALookupServiceNext之后,bytes数组pQuerySet中便包含了远程设备的地址信息,下面我们需要把它找出来。通过阅读SDK中WSAQUERYSET结构的说明和计算每个成员的位置之后,我们写出如下代码:

以下是引用片段:
int num5 = BitConverter.ToInt32(buffer1, 0x30);
  int num6 = Marshal.ReadInt32((IntPtr) num5, 8);
  int num7 = Marshal.ReadInt32((IntPtr) num5, 12);
  SocketAddress address1 = new SocketAddress(AddressFamily.Unspecified, num7);

  因为.net框架的地址族里面没有蓝牙,所以我们这里用的是AddressFamily.Unspecified。

  然后的工作就是从中获取远程设备的ID了:

  前面我们已经计算出,这个Address里面的前六个字节是byte数组形式的设备ID,第七到第二十二个字节是蓝牙的Service Guid,在后面四个字节是端口号,所以我们只需要分别提取出来即可。

  四. 监听服务

  监听服务调用的是非托管API WSASetService,其原型是

以下是引用片段:
INT WSASetService(
  LPWSAQUERYSET lpqsRegInfo,
  WSAESETSERVICEOP essoperation,
  DWORD dwControlFlags
  );

  可以看到关键也是第一个参数,lpqsRegInfo,这也是一个struct,我们的包装方法与前面的发现设备采用的方法类似,做蓝牙通信时要注意其成员要如下设置:

以下是引用片段:
lpqsRegInfodwSizesizeof(WSAQUERYSET)
  lpszServiceInstanceNameNot supported on Windows CE. Set to 0.
  lpServiceClassIdNot supported on Windows CE. Set to 0.
  dwNameSpaceNS_BTH.
  dwNumberOfCsAddrsNot supported on Windows CE. Set to 0.
  IpcsaBufferNot supported on Windows CE. Set to 0.
  lpBlobPoints to a BTHNS_SETBLOB structure, containing information about the service to be added.
  *
  All other WSAQUERYSET fields are ignored.

  五. 连接

  我们知道,IrDA中连接远程服务是使用方法System.Net.Sockets.IrDAClient类中的Connect方法。而这个方法又是调用的Socket类中的Connect方法。而Socket类是一个比较抽象的类,它并不绑定某个具体的地址族、SocketType和protocolType,所以在实例化的时候,需要指定这三个参数。我们也知道,在IrDA中,这三个参数分别是AddressFamily.Irda, SocketType.Stream,和ProtocolType.IP,那么在蓝牙中这三个参数分别是什么呢?我们好像找不到。

  且慢,真是这样吗?

  我们知道在.net中,这三个参数都是枚举值,而枚举在默认情况下,你可以认为就是int值的替代表现。

  我们该如何知道这三个参数到底是什么呢?

  还是先看Socket类的Connect方法。

  我们查查有关资料,可以知道这个方法实际上是调用的一个非托管函数:

以下是引用片段:
[DllImport("mscoree", EntryPoint="@339")]
  public static extern int connect(int s, byte[] name, int namelen);

  也就是非托管的Socket API。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章