用C#开发.NET CF 蓝牙通信模块
生活随笔
收集整理的這篇文章主要介紹了
用C#开发.NET CF 蓝牙通信模块
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
www.itdocx.com
在Windows Mobile軟件開發(fā)中.Net正扮演著日益重要的角色,我們已經(jīng)可以看到很多用.Net CF開發(fā)的軟件,這些軟件涉及到了日常應(yīng)用的方方面面。在智能設(shè)備的軟件開發(fā)中,無線互聯(lián)是一個相當(dāng)重要的一塊,我們可以看到,紅外幾乎是所有智能設(shè)備的標(biāo)配,而藍(lán)牙也日益在越來越多的智能設(shè)備上出現(xiàn),有了硬件,顯然要有相應(yīng)的軟件相關(guān)的應(yīng)用。
我們也知道,用.NET CF開發(fā)紅外通信應(yīng)用時相當(dāng)輕松的,因為.NET CF中有一個命名空間System.Net.IrDA就是用于紅外通信的通信模塊。但是,.NET CF中還沒有關(guān)于藍(lán)牙通信的模塊,所以目前來講做這方面的開發(fā)還有一定的困難。下面,就談?wù)勅绾斡肅#開發(fā).NET CF藍(lán)牙通信模塊。
一. 基本要點
首先明確一點,因為涉及到驅(qū)動硬件的問題,所以僅靠了解C#開發(fā)的相關(guān)知識顯然是無法完成開發(fā)的,我們必須對C++開發(fā)有所了解。但是為了簡單起見,我們不希望用C++寫半行代碼,所有的編碼工作全部使用C#,也就是說,使用的開發(fā)環(huán)境只需要使用Visual Studio.net,不需要用其他的編輯器。
作為開發(fā)這類驅(qū)動硬件的程序的知識準(zhǔn)備,您需要了解C++的基本知識,知道頭文件是怎么一回事,知道托管代碼如何與非托管代碼交互。因為本文的核心是說明如何開發(fā).net CF藍(lán)牙通信模塊,所以前述這些準(zhǔn)備知識并不作講述。
二. 關(guān)于藍(lán)牙
做藍(lán)牙通信模塊開發(fā),自然先要知道藍(lán)牙通信是怎么一回事。在我看來,藍(lán)牙通信應(yīng)該和紅外通信模塊類似,當(dāng)然我是從開發(fā)者的角度來講,抽象化以后應(yīng)該就是這樣,當(dāng)然藍(lán)牙和紅外通信也有很多不一樣的地方,這在面向?qū)ο笤O(shè)計里面怎么講,我想一定有很多人理解的比我透徹。好了,這就是我們的基本思路了。我曾經(jīng)在網(wǎng)上查過關(guān)于藍(lán)牙開發(fā)的文章,很多人在.net CF開發(fā)中把藍(lán)牙通信當(dāng)作一個串行通信來處理,這也是不錯的,但是我不是很喜歡,因為這樣做的話,并不是針對藍(lán)牙來開發(fā)的,換言之,在使用過程中,需要先手動開啟藍(lán)牙,配對,連接,建立串行通道,然后開啟應(yīng)用程序使用,你還要在應(yīng)用程序中設(shè)置串行端口,對最終用戶來講,這是非常麻煩的。我覺得,這樣的解決方案冠上藍(lán)牙通信的名頭簡直就是……不多說了,書歸正傳。
在紅外通信中,我們知道,設(shè)備的DeviceID是一個Byte數(shù)組,那么藍(lán)牙設(shè)備的DeviceID什么樣子呢?我想這個大家都很清楚,是一串以“:”分隔的16進制數(shù)字。
紅外通信中,一般而言紅外并沒有開啟、關(guān)閉之類的狀態(tài),但是藍(lán)牙有開啟、關(guān)閉、可發(fā)現(xiàn)三種狀態(tài)。
紅外沒有安全設(shè)置,而藍(lán)牙有安全設(shè)置,所以我們需要對藍(lán)牙設(shè)備進行配對,而紅外通信這部需要。
我們查看.net的Socket地址族里有IrDA,但是沒有藍(lán)牙相關(guān)的地址族,這是我們需要解決的問題。
三. 獲取設(shè)備ID
1.獲取本地設(shè)備的ID
我們查看Window CE 4.2的SDK文檔,得知獲取本地設(shè)備ID的函數(shù)是BthReadLocalAddr,在btdrt.dll中。SDK文檔中的英文原文是這樣的:“This function retrieves the Bluetooth address of the current device.”好了,知道了這個就好說了:
首先封裝本地托管函數(shù):
這個函數(shù)得到的本地DeviceID也是一組byte數(shù)組,為了向人們顯示出來,我們要把它變?yōu)镾tring:
2.獲取遠(yuǎn)程設(shè)備的ID
其實談到獲取遠(yuǎn)程設(shè)備的ID就涉及到如何去發(fā)現(xiàn)遠(yuǎn)程設(shè)備了,所以這里就一并把發(fā)現(xiàn)設(shè)備的方法也說明了吧。 發(fā)現(xiàn)設(shè)備需要用到三個Winsock API,分別是WSALookupServiceBegin、WSALookupServiceNext和WSALookupServiceEnd,這三個API到底起什么作用可以去查看Windows CE 4.2的SDK,這里就不詳細(xì)解釋了,只談一下幾個需要注意的地方。
WSALookupServiceBegin的函數(shù)原形是這樣的:
我們用托管代碼進行包裝:
可以看到,本來lpqsRestrictions是一個struct,經(jīng)過包裝后在托管代碼中成為了byte[],我們計算好該struct大概要占用多少個byte,struct中每一個成員在byte數(shù)組中的位置是怎樣的,裝配出來就好了。
由于是針對藍(lán)牙作的開發(fā),所以我們要查看一下這些參數(shù)應(yīng)該是哪些值。Windows CE 4.2的SDK中說,藍(lán)牙開發(fā)時,struct LPWSAQUERYSET中的如下成員應(yīng)當(dāng)為這些值:
具體什么意思各位可以自己去理解,我想比我翻譯出來要好些,畢竟我英語很差的。根據(jù)以上要求,我們這樣裝配pQuerySet:
另外的兩個API也照類似方法調(diào)用即可。
在調(diào)用了WSALookupServiceNext之后,bytes數(shù)組pQuerySet中便包含了遠(yuǎn)程設(shè)備的地址信息,下面我們需要把它找出來。通過閱讀SDK中WSAQUERYSET結(jié)構(gòu)的說明和計算每個成員的位置之后,我們寫出如下代碼:
可以看到關(guān)鍵也是第一個參數(shù),lpqsRegInfo,這也是一個struct,我們的包裝方法與前面的發(fā)現(xiàn)設(shè)備采用的方法類似,做藍(lán)牙通信時要注意其成員要如下設(shè)置:
五. 連接
我們知道,IrDA中連接遠(yuǎn)程服務(wù)是使用方法System.Net.Sockets.IrDAClient類中的Connect方法。而這個方法又是調(diào)用的Socket類中的Connect方法。而Socket類是一個比較抽象的類,它并不綁定某個具體的地址族、SocketType和protocolType,所以在實例化的時候,需要指定這三個參數(shù)。我們也知道,在IrDA中,這三個參數(shù)分別是AddressFamily.Irda, SocketType.Stream,和ProtocolType.IP,那么在藍(lán)牙中這三個參數(shù)分別是什么呢?我們好像找不到。
且慢,真是這樣嗎?
我們知道在.net中,這三個參數(shù)都是枚舉值,而枚舉在默認(rèn)情況下,你可以認(rèn)為就是int值的替代表現(xiàn)。
我們該如何知道這三個參數(shù)到底是什么呢?
還是先看Socket類的Connect方法。
我們查查有關(guān)資料,可以知道這個方法實際上是調(diào)用的一個非托管函數(shù):
也就是非托管的Socket API。
我們看Windows CE 4.2的SDK,可以看到,在使用藍(lán)牙進行連接的時候,需要使用WinSock擴展。我們還可以看到,在使用藍(lán)牙進行連接的時候,三個參數(shù)分別應(yīng)當(dāng)是AF_BTH、SOCK_STREAM和BTHPROTO_RFCOMM,至于這三個參數(shù)分別代表什么,我們就要查看相關(guān)的頭文件了。
我們找到ws2bth.h頭文件,可以看到AF_BTH代表十進制數(shù)32,而BTHPROTO_RFCOMM代表十六進制數(shù)0x0003,恰好和ProtocolType.Ggp代表的數(shù)值是一致的。所以,我們在實例化Socket時是這么寫的:
Socket實例化出來了,其他的當(dāng)然就都好說了,這里不再贅述。
六. 藍(lán)牙的安全設(shè)置
藍(lán)牙比紅外多了安全方面的設(shè)置,所以就需要多一些代碼來處理這些。具體也就不多說了,其實也就是一些非托管代碼的包裝調(diào)用,這些API在Btdrt.dll中:
獲取配對碼請求:
設(shè)置配對碼:
比較麻煩點的是配對,總共有三步操作:
首先是創(chuàng)建ACL連接:
然后是配對碼驗證:
然后一定要關(guān)閉連接:
七. 設(shè)置藍(lán)牙無線電狀態(tài)
我們知道,藍(lán)牙無線電有打開、關(guān)閉、可發(fā)現(xiàn)三種狀態(tài),那么我們?nèi)绾螌崿F(xiàn)編程控制呢?
我想這個一定大家都知道了,因為網(wǎng)上有很多關(guān)于這個的文章:
先寫一個枚舉:
然后寫一個函數(shù)調(diào)用非托管代碼即可:
獲取無線電狀態(tài)的話就用下面的函數(shù):
八. 已知的問題
可能是因為藍(lán)牙控制軟件還沒有實現(xiàn)標(biāo)準(zhǔn)化或者還是其他的問題,我們發(fā)現(xiàn)根據(jù)Windows CE 4.2 SDK 使用Winsock 擴展做的藍(lán)牙開發(fā)有一個問題,而且不論是本文中所述的托管代碼還是其他的非托管代碼,只要是用的這種思路用Winsock 2做的開發(fā)都會存在這樣一個問題,那就是不是在所有的Windows Mobile設(shè)備上都能正常運行。經(jīng)過我的測試,我發(fā)現(xiàn)在很多使用另行開發(fā)的藍(lán)牙控制軟件的設(shè)備上,如聯(lián)想ET560、華碩MyPAL A730上都無法運行,而在沒有另行開發(fā)藍(lán)牙控制軟件的設(shè)備上是可以正常運行的,我不知道這是什么原因,初步推測可能是廠商另行開發(fā)的藍(lán)牙控制軟件屏蔽了微軟的API的緣故,到底是不是這樣,還得請高人指點。
在Windows Mobile軟件開發(fā)中.Net正扮演著日益重要的角色,我們已經(jīng)可以看到很多用.Net CF開發(fā)的軟件,這些軟件涉及到了日常應(yīng)用的方方面面。在智能設(shè)備的軟件開發(fā)中,無線互聯(lián)是一個相當(dāng)重要的一塊,我們可以看到,紅外幾乎是所有智能設(shè)備的標(biāo)配,而藍(lán)牙也日益在越來越多的智能設(shè)備上出現(xiàn),有了硬件,顯然要有相應(yīng)的軟件相關(guān)的應(yīng)用。
我們也知道,用.NET CF開發(fā)紅外通信應(yīng)用時相當(dāng)輕松的,因為.NET CF中有一個命名空間System.Net.IrDA就是用于紅外通信的通信模塊。但是,.NET CF中還沒有關(guān)于藍(lán)牙通信的模塊,所以目前來講做這方面的開發(fā)還有一定的困難。下面,就談?wù)勅绾斡肅#開發(fā).NET CF藍(lán)牙通信模塊。
一. 基本要點
首先明確一點,因為涉及到驅(qū)動硬件的問題,所以僅靠了解C#開發(fā)的相關(guān)知識顯然是無法完成開發(fā)的,我們必須對C++開發(fā)有所了解。但是為了簡單起見,我們不希望用C++寫半行代碼,所有的編碼工作全部使用C#,也就是說,使用的開發(fā)環(huán)境只需要使用Visual Studio.net,不需要用其他的編輯器。
作為開發(fā)這類驅(qū)動硬件的程序的知識準(zhǔn)備,您需要了解C++的基本知識,知道頭文件是怎么一回事,知道托管代碼如何與非托管代碼交互。因為本文的核心是說明如何開發(fā).net CF藍(lán)牙通信模塊,所以前述這些準(zhǔn)備知識并不作講述。
二. 關(guān)于藍(lán)牙
做藍(lán)牙通信模塊開發(fā),自然先要知道藍(lán)牙通信是怎么一回事。在我看來,藍(lán)牙通信應(yīng)該和紅外通信模塊類似,當(dāng)然我是從開發(fā)者的角度來講,抽象化以后應(yīng)該就是這樣,當(dāng)然藍(lán)牙和紅外通信也有很多不一樣的地方,這在面向?qū)ο笤O(shè)計里面怎么講,我想一定有很多人理解的比我透徹。好了,這就是我們的基本思路了。我曾經(jīng)在網(wǎng)上查過關(guān)于藍(lán)牙開發(fā)的文章,很多人在.net CF開發(fā)中把藍(lán)牙通信當(dāng)作一個串行通信來處理,這也是不錯的,但是我不是很喜歡,因為這樣做的話,并不是針對藍(lán)牙來開發(fā)的,換言之,在使用過程中,需要先手動開啟藍(lán)牙,配對,連接,建立串行通道,然后開啟應(yīng)用程序使用,你還要在應(yīng)用程序中設(shè)置串行端口,對最終用戶來講,這是非常麻煩的。我覺得,這樣的解決方案冠上藍(lán)牙通信的名頭簡直就是……不多說了,書歸正傳。
在紅外通信中,我們知道,設(shè)備的DeviceID是一個Byte數(shù)組,那么藍(lán)牙設(shè)備的DeviceID什么樣子呢?我想這個大家都很清楚,是一串以“:”分隔的16進制數(shù)字。
紅外通信中,一般而言紅外并沒有開啟、關(guān)閉之類的狀態(tài),但是藍(lán)牙有開啟、關(guān)閉、可發(fā)現(xiàn)三種狀態(tài)。
紅外沒有安全設(shè)置,而藍(lán)牙有安全設(shè)置,所以我們需要對藍(lán)牙設(shè)備進行配對,而紅外通信這部需要。
我們查看.net的Socket地址族里有IrDA,但是沒有藍(lán)牙相關(guān)的地址族,這是我們需要解決的問題。
三. 獲取設(shè)備ID
1.獲取本地設(shè)備的ID
我們查看Window CE 4.2的SDK文檔,得知獲取本地設(shè)備ID的函數(shù)是BthReadLocalAddr,在btdrt.dll中。SDK文檔中的英文原文是這樣的:“This function retrieves the Bluetooth address of the current device.”好了,知道了這個就好說了:
首先封裝本地托管函數(shù):
| [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthReadLocalAddr(byte[] pba); |
這個函數(shù)得到的本地DeviceID也是一組byte數(shù)組,為了向人們顯示出來,我們要把它變?yōu)镾tring:
| string text1 = ""; text1 = text1 + pba[5].ToString("X2") + ":"; text1 = text1 + pba [4].ToString("X2") + ":"; text1 = text1 + pba [3].ToString("X2") + ":"; text1 = text1 + pba [2].ToString("X2") + ":"; text1 = text1 + pba [1].ToString("X2") + ":"; return (text1 + pba [0].ToString("X2")); |
2.獲取遠(yuǎn)程設(shè)備的ID
其實談到獲取遠(yuǎn)程設(shè)備的ID就涉及到如何去發(fā)現(xiàn)遠(yuǎn)程設(shè)備了,所以這里就一并把發(fā)現(xiàn)設(shè)備的方法也說明了吧。 發(fā)現(xiàn)設(shè)備需要用到三個Winsock API,分別是WSALookupServiceBegin、WSALookupServiceNext和WSALookupServiceEnd,這三個API到底起什么作用可以去查看Windows CE 4.2的SDK,這里就不詳細(xì)解釋了,只談一下幾個需要注意的地方。
WSALookupServiceBegin的函數(shù)原形是這樣的:
| INT WSALookupServiceBegin( LPWSAQUERYSET lpqsRestrictions, DWORD dwControlFlags, LPHANDLE lphLookup ); |
我們用托管代碼進行包裝:
| [DllImport("ws2.dll", EntryPoint="WSALookupServiceBegin", SetLastError=true)] public static extern int CeLookupServiceBegin(byte[] pQuerySet, LookupFlags dwFlags, ref int lphLookup); |
可以看到,本來lpqsRestrictions是一個struct,經(jīng)過包裝后在托管代碼中成為了byte[],我們計算好該struct大概要占用多少個byte,struct中每一個成員在byte數(shù)組中的位置是怎樣的,裝配出來就好了。
由于是針對藍(lán)牙作的開發(fā),所以我們要查看一下這些參數(shù)應(yīng)該是哪些值。Windows CE 4.2的SDK中說,藍(lán)牙開發(fā)時,struct LPWSAQUERYSET中的如下成員應(yīng)當(dāng)為這些值:
| 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. |
具體什么意思各位可以自己去理解,我想比我翻譯出來要好些,畢竟我英語很差的。根據(jù)以上要求,我們這樣裝配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也照類似方法調(diào)用即可。
在調(diào)用了WSALookupServiceNext之后,bytes數(shù)組pQuerySet中便包含了遠(yuǎn)程設(shè)備的地址信息,下面我們需要把它找出來。通過閱讀SDK中WSAQUERYSET結(jié)構(gòu)的說明和計算每個成員的位置之后,我們寫出如下代碼:
| 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框架的地址族里面沒有藍(lán)牙,所以我們這里用的是AddressFamily.Unspecified。
然后的工作就是從中獲取遠(yuǎn)程設(shè)備的ID了:
前面我們已經(jīng)計算出,這個Address里面的前六個字節(jié)是byte數(shù)組形式的設(shè)備ID,第七到第二十二個字節(jié)是藍(lán)牙的Service Guid,在后面四個字節(jié)是端口號,所以我們只需要分別提取出來即可。
四. 監(jiān)聽服務(wù)
監(jiān)聽服務(wù)調(diào)用的是非托管API WSASetService,其原型是
| INT WSASetService( LPWSAQUERYSET lpqsRegInfo, WSAESETSERVICEOP essoperation, DWORD dwControlFlags ); |
可以看到關(guān)鍵也是第一個參數(shù),lpqsRegInfo,這也是一個struct,我們的包裝方法與前面的發(fā)現(xiàn)設(shè)備采用的方法類似,做藍(lán)牙通信時要注意其成員要如下設(shè)置:
| lpqsRegInfo | dwSize | sizeof(WSAQUERYSET) |
| ? | lpszServiceInstanceName | Not supported on Windows CE. Set to 0. |
| ? | lpServiceClassId | Not supported on Windows CE. Set to 0. |
| ? | dwNameSpace | NS_BTH. |
| ? | dwNumberOfCsAddrs | Not supported on Windows CE. Set to 0. |
| ? | IpcsaBuffer | Not supported on Windows CE. Set to 0. |
| ? | lpBlob | Points to a BTHNS_SETBLOB structure, containing information about the service to be added. |
| ? | * | All other WSAQUERYSET fields are ignored. |
五. 連接
我們知道,IrDA中連接遠(yuǎn)程服務(wù)是使用方法System.Net.Sockets.IrDAClient類中的Connect方法。而這個方法又是調(diào)用的Socket類中的Connect方法。而Socket類是一個比較抽象的類,它并不綁定某個具體的地址族、SocketType和protocolType,所以在實例化的時候,需要指定這三個參數(shù)。我們也知道,在IrDA中,這三個參數(shù)分別是AddressFamily.Irda, SocketType.Stream,和ProtocolType.IP,那么在藍(lán)牙中這三個參數(shù)分別是什么呢?我們好像找不到。
且慢,真是這樣嗎?
我們知道在.net中,這三個參數(shù)都是枚舉值,而枚舉在默認(rèn)情況下,你可以認(rèn)為就是int值的替代表現(xiàn)。
我們該如何知道這三個參數(shù)到底是什么呢?
還是先看Socket類的Connect方法。
我們查查有關(guān)資料,可以知道這個方法實際上是調(diào)用的一個非托管函數(shù):
| [DllImport("mscoree", EntryPoint="@339")] public static extern int connect(int s, byte[] name, int namelen); |
也就是非托管的Socket API。
我們看Windows CE 4.2的SDK,可以看到,在使用藍(lán)牙進行連接的時候,需要使用WinSock擴展。我們還可以看到,在使用藍(lán)牙進行連接的時候,三個參數(shù)分別應(yīng)當(dāng)是AF_BTH、SOCK_STREAM和BTHPROTO_RFCOMM,至于這三個參數(shù)分別代表什么,我們就要查看相關(guān)的頭文件了。
我們找到ws2bth.h頭文件,可以看到AF_BTH代表十進制數(shù)32,而BTHPROTO_RFCOMM代表十六進制數(shù)0x0003,恰好和ProtocolType.Ggp代表的數(shù)值是一致的。所以,我們在實例化Socket時是這么寫的:
| new Socket((AddressFamily) 0x20, SocketType.Stream, ProtocolType.Ggp); |
Socket實例化出來了,其他的當(dāng)然就都好說了,這里不再贅述。
六. 藍(lán)牙的安全設(shè)置
藍(lán)牙比紅外多了安全方面的設(shè)置,所以就需要多一些代碼來處理這些。具體也就不多說了,其實也就是一些非托管代碼的包裝調(diào)用,這些API在Btdrt.dll中:
獲取配對碼請求:
| [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthGetPINRequest(byte[] pba); |
設(shè)置配對碼:
| [DllImport("btdrt.dll", SetLastError=true)] public static extern int BthSetPIN(byte[] pba, int cPinLength, byte[] ppin); |
比較麻煩點的是配對,總共有三步操作:
首先是創(chuàng)建ACL連接:
| [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthCreateACLConnection(byte[] pbt, ref ushort phandle); |
然后是配對碼驗證:
| [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthAuthenticate(byte[] pbt); |
然后一定要關(guān)閉連接:
| [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthCloseConnection(ushort handle); |
七. 設(shè)置藍(lán)牙無線電狀態(tài)
我們知道,藍(lán)牙無線電有打開、關(guān)閉、可發(fā)現(xiàn)三種狀態(tài),那么我們?nèi)绾螌崿F(xiàn)編程控制呢?
我想這個一定大家都知道了,因為網(wǎng)上有很多關(guān)于這個的文章:
先寫一個枚舉:
| public enum RadioMode { Connectable = 1, Discoverable = 2, PowerOff = 0 } |
然后寫一個函數(shù)調(diào)用非托管代碼即可:
| [DllImport("BthUtil.dll", SetLastError=true)] public static extern int BthSetMode(RadioMode dwMode); |
獲取無線電狀態(tài)的話就用下面的函數(shù):
| [DllImport("BthUtil.dll", SetLastError=true)] public static extern int BthGetMode(ref RadioMode dwMode); |
八. 已知的問題
可能是因為藍(lán)牙控制軟件還沒有實現(xiàn)標(biāo)準(zhǔn)化或者還是其他的問題,我們發(fā)現(xiàn)根據(jù)Windows CE 4.2 SDK 使用Winsock 擴展做的藍(lán)牙開發(fā)有一個問題,而且不論是本文中所述的托管代碼還是其他的非托管代碼,只要是用的這種思路用Winsock 2做的開發(fā)都會存在這樣一個問題,那就是不是在所有的Windows Mobile設(shè)備上都能正常運行。經(jīng)過我的測試,我發(fā)現(xiàn)在很多使用另行開發(fā)的藍(lán)牙控制軟件的設(shè)備上,如聯(lián)想ET560、華碩MyPAL A730上都無法運行,而在沒有另行開發(fā)藍(lán)牙控制軟件的設(shè)備上是可以正常運行的,我不知道這是什么原因,初步推測可能是廠商另行開發(fā)的藍(lán)牙控制軟件屏蔽了微軟的API的緣故,到底是不是這樣,還得請高人指點。
轉(zhuǎn)載于:https://www.cnblogs.com/slcfhr/archive/2006/09/01/492612.html
總結(jié)
以上是生活随笔為你收集整理的用C#开发.NET CF 蓝牙通信模块的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 白领丽人:这六行盛产“钻石王老五”
- 下一篇: 如何根据用户IP得到用户所在位置。