小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

藍(lán)牙技術(shù),第 1 部分: 使用 JSR-82 和 OBEX 進(jìn)行文件傳輸

 newencn 2011-04-13

藍(lán)牙協(xié)議棧允許采用多種方法,包括 RFCOMM 和 Object Exchange(OBEX),在設(shè)備之間發(fā)送和接收文件。如果想發(fā)送和接收流數(shù)據(jù)(而且想采用傳統(tǒng)的串口應(yīng)用程序,并給它加上藍(lán)牙支持),那么 RFCOMM 更好。反過(guò)來(lái),如果想發(fā)送對(duì)象數(shù)據(jù)以及關(guān)于負(fù)載的上下文和元數(shù)據(jù),則 OBEX 最好。在這篇文章中,將熟悉用來(lái)控制藍(lán)牙設(shè)備的 Java 語(yǔ)言庫(kù),并學(xué)習(xí)如何使用 JSR-82 API 和 OBEX 在客戶機(jī)和服務(wù)器之間傳輸文件。

藍(lán)牙是多家移動(dòng)設(shè)備制造商選擇的無(wú)線協(xié)議,擁有多項(xiàng)吸引人的特性,最重要的是它在數(shù)據(jù)傳輸上的低能耗。截止 2004 年 6 月,每周交付的支持藍(lán)牙的設(shè)備超過(guò)五百萬(wàn)臺(tái),這項(xiàng)技術(shù)在消費(fèi)電子市場(chǎng)上擁有強(qiáng)大的滲透率。

藍(lán)牙協(xié)議回顧

目前市場(chǎng)上設(shè)備中運(yùn)行的藍(lán)牙協(xié)議有三個(gè)版本 —— 分別是版本 1.1、1.2 AFH 和 2.0+EDR。這沒(méi)給開(kāi)發(fā)人員帶來(lái)任何問(wèn)題,因?yàn)樾掳姹镜膮f(xié)議與以前的版本兼容。表 1 顯示了目前可用的藍(lán)牙版本的一些相似性與區(qū)別。

表 1. 藍(lán)牙協(xié)議版本
版本 原始數(shù)據(jù)速率 通信范圍(英尺) 說(shuō)明
Bluetooth 1.1 1 Mbps 30-300 市場(chǎng)上部署得最廣泛的藍(lán)牙版本。
Bluetooth 1.2 AFH 1 Mbps 30-300 包含高級(jí)頻率跳躍技術(shù),可以與 WiFi 網(wǎng)絡(luò)更好地并存。
Bluetooth 2.0+EDR 3 Mbps 30-300 包含增強(qiáng)數(shù)據(jù)速率技術(shù),可以用更高的速度傳輸數(shù)據(jù)。

現(xiàn)在,讓我們回顧一下控制藍(lán)牙設(shè)備的固件/軟件:棧。

藍(lán)牙協(xié)議棧

藍(lán)牙棧的目的是什么呢?棧是控制藍(lán)牙設(shè)備的軟件(和固件)。圖 1 顯示了協(xié)議棧的細(xì)節(jié)。


圖 1. 藍(lán)牙協(xié)議棧
藍(lán)牙協(xié)議棧
  • 棧的最底層是 HCI,即主機(jī)控制器接口(Host Controller Interface)。這一層顧名思義就是主機(jī)(計(jì)算機(jī))和控制器(藍(lán)牙設(shè)備)之間的接口??梢钥吹?,其他所有的層都要經(jīng)過(guò) HCI。
  • HCI 上面的一層是 L2CAP,即邏輯鏈接控制器適配協(xié)議(Logical Link Controller Adaptation Protocol)。這一層充當(dāng)其他所有層的數(shù)據(jù)多路復(fù)用器。
  • 接下來(lái)一層是 BNEP,即藍(lán)牙網(wǎng)絡(luò)封裝協(xié)議(Bluetooth Network Encapsulation Protocol)。使用 BNEP,可以在藍(lán)牙上運(yùn)行其他網(wǎng)絡(luò)協(xié)議,例如 IP、TCP 和 UDP。
  • RFCOMM 稱作虛擬串口協(xié)議(virtual serial port protocol),因?yàn)樗试S藍(lán)牙設(shè)備模擬串口的功能。
  • OBEX 協(xié)議層是在 RFCOMM 層上面實(shí)現(xiàn)的,如果想把數(shù)據(jù)以對(duì)象(例如文件)的形式傳輸,那么 OBEX 很有用。
  • SDP 是服務(wù)發(fā)現(xiàn)協(xié)議(Service Discovery Protocol)層,用于在遠(yuǎn)程藍(lán)牙設(shè)備上尋找服務(wù)。
  • 最后兩層是 AVCTP 和 AVDTP,用于藍(lán)牙上音頻和視頻的控制發(fā)布。AVCTP 和 AVDTP 是藍(lán)牙協(xié)議中增加的相對(duì)較新的層;如果想控制媒體播放器的功能或者想以立體聲播放音頻流,則要使用它們。

發(fā)送文件:RFCOMM 還是 OBEX?

我們先來(lái)看看棧中用來(lái)發(fā)送數(shù)據(jù)的兩個(gè)簡(jiǎn)單協(xié)議 RFCOMM 和 OBEX,并比較使用它們傳送文件的優(yōu)勢(shì)和不足。

可以采用 RFCOMM 或 OBEX 在藍(lán)牙設(shè)備之間發(fā)送和接收文件。但是,如果想發(fā)送和接收流數(shù)據(jù),則 RFCOMM 是更好的選擇,就像使用傳統(tǒng)的串口一樣。在現(xiàn)實(shí)世界中,如果想使用傳統(tǒng)的串口應(yīng)用程序,并讓它能使用藍(lán)牙,就應(yīng)當(dāng)使用 RFCOMM。如果要在藍(lán)牙設(shè)備之間發(fā)送簡(jiǎn)單的文本字符串(例如在聊天應(yīng)用程序中),那么使用 OBEX 可能沒(méi)有太大優(yōu)勢(shì)。在這種情況下,應(yīng)當(dāng)使用 RFCOMM 或 L2CAP。

另一方面,如果想發(fā)送對(duì)象數(shù)據(jù)(例如文件),則 OBEX 最合適。使用 OBEX 不僅可以發(fā)送數(shù)據(jù),而且還能發(fā)送關(guān)于負(fù)載的上下文或元數(shù)據(jù)。例如,在使用 OBEX 發(fā)送文件時(shí),還能夠發(fā)送關(guān)于文件的其他有用信息,例如文件名稱、文件類型、文件尺寸或者其他任何對(duì)文件進(jìn)行描述的內(nèi)容。

那么,既然已經(jīng)決定了使用藍(lán)牙時(shí)通過(guò) OBEX 發(fā)送對(duì)象數(shù)據(jù)文件,那么我們來(lái)看看使用 Java 語(yǔ)言對(duì)藍(lán)牙設(shè)備進(jìn)行控制的官方庫(kù)。


探索 JSR-82 API

JSR-82 是用于藍(lán)牙無(wú)線技術(shù)的官方 Java API。可使用這個(gè) API 創(chuàng)建可執(zhí)行以下功能的應(yīng)用程序:

  • 判斷和檢測(cè)自己的藍(lán)牙設(shè)備的屬性
  • 發(fā)現(xiàn)設(shè)備通信范圍內(nèi)的藍(lán)牙設(shè)備
  • 在遠(yuǎn)程藍(lán)牙設(shè)備上搜索服務(wù)
  • 創(chuàng)建可以與遠(yuǎn)程藍(lán)牙服務(wù)器通信的藍(lán)牙客戶機(jī)應(yīng)用程序
  • 創(chuàng)建能夠?yàn)樗{(lán)牙客戶機(jī)的請(qǐng)求提供服務(wù)的藍(lán)牙服務(wù)器應(yīng)用程序

JSR-82 包含兩個(gè)包,即 javax.bluetoothjavax.obex。您自己的藍(lán)牙設(shè)備由 javax.bluetooth.LocalDevice 類表示,所有的遠(yuǎn)程藍(lán)牙設(shè)備由 javax.bluetooth.RemoteDevice 類表示。

javax.bluetooth.DiscoveryAgent 類是個(gè)有幫助的類,它讓您可以發(fā)現(xiàn)附近的遠(yuǎn)程藍(lán)牙設(shè)備,并為區(qū)域內(nèi)的每個(gè)藍(lán)牙設(shè)備返回一個(gè) javax.bluetooth.RemoteDevice。也可以使用 javax.bluetooth.DiscoveryAgent 在已經(jīng)發(fā)現(xiàn)的遠(yuǎn)程設(shè)備上搜索服務(wù)。

如果想在發(fā)生發(fā)現(xiàn)事件的時(shí)候得到通知,則需要實(shí)現(xiàn) javax.bluetooth.DiscoveryListener 接口的方法 。這一切聽(tīng)都來(lái)都很簡(jiǎn)單,是不是?但是,當(dāng)想要?jiǎng)?chuàng)建 OBEX 應(yīng)用程序的時(shí)候,會(huì)變得復(fù)雜一些。


OBEX 的語(yǔ)義

也許您不知道,OBEX 并不是藍(lán)牙本身的協(xié)議,實(shí)際是由無(wú)線數(shù)據(jù)協(xié)會(huì)創(chuàng)建的。因?yàn)?OBEX 是已采納的 協(xié)議,所以 Java 藍(lán)牙 API 的作者決定為 OBEX 應(yīng)用程序單獨(dú)創(chuàng)建一個(gè)包;這樣,就可以使用 Java 創(chuàng)建出能夠在任何傳輸機(jī)制(例如紅外或 TCP/IP)而不僅僅是在藍(lán)牙上工作的 OBEX 應(yīng)用程序。

在使用藍(lán)牙 API 創(chuàng)建 OBEX 應(yīng)用程序時(shí),將使用 javax.obex 包中的一些類和接口。正如我在前面提到過(guò)的,藍(lán)牙協(xié)議棧中的 OBEX 層實(shí)際是面向藍(lán)牙設(shè)備間的文件傳輸而優(yōu)化的,所以就像傳統(tǒng)的 FTP 一樣,OBEX 應(yīng)用程序擁有像 GETPUT 這樣的操作。

到底什么是 OBEX 操作?

OBEX 操作

當(dāng)客戶機(jī)和服務(wù)器在一個(gè) OBEX 會(huì)話內(nèi)通信時(shí),它們的交互叫做操作。對(duì)于每個(gè)從客戶機(jī)發(fā)出的操作,服務(wù)器給出一個(gè)響應(yīng),指明操作的狀態(tài)。要真正了解 OBEX 客戶機(jī)和服務(wù)器的操作和響應(yīng)的工作方式,請(qǐng)參見(jiàn)圖 2:


圖 2. OBEX 操作和響應(yīng)代碼
OBEX 操作和響應(yīng)代碼

如果從電話向打印機(jī)發(fā)送文件,就像圖 2 中表示的那樣,需要什么呢?首先,在創(chuàng)建 OBEX 會(huì)話之前,先要建立一個(gè)傳輸?shù)倪B接(藍(lán)牙、紅外、TCP/IP 等等)。因?yàn)檫@篇文章是關(guān)于藍(lán)牙的,所以毫不奇怪我要使用的底層傳輸機(jī)制是藍(lán)牙。

在傳輸連接已經(jīng)建立之后,藍(lán)牙客戶機(jī)需要發(fā)出 CONNECT 操作。如果藍(lán)牙服務(wù)器(在這個(gè)示例中,是打印機(jī))想接受新客戶機(jī)來(lái)使用它的服務(wù)(例如打印服務(wù)),那么它就用表示成功的響應(yīng)代碼 160 對(duì)客戶機(jī)進(jìn)行響應(yīng)。如果打印機(jī)不想接受新客戶機(jī),那么它可能用響應(yīng)代碼 211 來(lái)響應(yīng),這個(gè)代碼代表 “OBEX SERVICE UNAVAILABLE”。

現(xiàn)在假設(shè)打印機(jī)接受了 CONNECT 操作,那么現(xiàn)在就在客戶機(jī)和服務(wù)器之間創(chuàng)建了一個(gè) OBEX 會(huì)話。現(xiàn)在有了 OBEX 會(huì)話,就能夠向 OBEX 服務(wù)器發(fā)送請(qǐng)求(請(qǐng)注意,請(qǐng)求和操作是同義的)。當(dāng)然,GETPUT 操作是自解釋的。但是,SETPATH 操作主要是在 OBEX 服務(wù)器具有文件系統(tǒng)時(shí)才使用。OBEX 客戶機(jī)發(fā)送 SETPATH 請(qǐng)求以指導(dǎo) OBEX 客戶機(jī)改變工作目錄(類似于 cd 命令)。SETPATH 操作后面通常跟著一個(gè) GETPUT 操作。要終止 OBEX 會(huì)話,客戶機(jī)需要發(fā)送 DISCONNECT 操作。如果成功,OBEX 服務(wù)器會(huì)用成功響應(yīng)代碼 160 進(jìn)行響應(yīng)。

現(xiàn)在對(duì)于 OBEX 的語(yǔ)義有了良好的理解,讓我們看看在 JSR-82 API 中,Java 語(yǔ)言、藍(lán)牙和 OBEX 是如何放在一起的。我先從服務(wù)器代碼開(kāi)始,因?yàn)榭蛻魴C(jī)代碼更復(fù)雜。


創(chuàng)建 OBEX 服務(wù)器應(yīng)用程序

我的服務(wù)器應(yīng)用程序叫做 FileServer.java,而且因?yàn)?“重要事情優(yōu)先”,所以我們先來(lái)看清單 1 中的 import 語(yǔ)句和類聲明。


清單 1. import 語(yǔ)句和類聲明
import javax.swing.*;
            import java.awt.*;
            import java.awt.event.*;
            import javax.microedition.io.*;
            import java.io.*;
            import javax.bluetooth.*;
            import javax.obex.*;
            public class FileServer extends ServerRequestHandler
            implements ActionListener{
            

如果想創(chuàng)建 OBEX 服務(wù)器,就需要擴(kuò)展 javax.obex.ServerRequestHandler 類。因?yàn)檫@個(gè)示例是 J2SE 應(yīng)用程序,所以我還想實(shí)現(xiàn) ActionListener 接口,這樣就能響應(yīng)按鈕點(diǎn)擊。當(dāng)用戶點(diǎn)擊啟動(dòng)服務(wù)器的按鈕時(shí),就會(huì)調(diào)用 actionPerformed() 方法(如清單 2 所示)。


清單 2. FilesServer.actionPerformed()
            public void actionPerformed(ActionEvent e) {
            startButton.setEnabled(false);
            try {
            UUID uuid = new UUID("8841", true);
            String url = "btgoep://localhost:" + uuid
            + ";name=FTP;authenticate=false;master=false;encrypt=false";
            SessionNotifier sn = (SessionNotifier)Connector.open(url);
            updateStatus("[server:] Now waiting for a client to connect");
            sn.acceptAndOpen(this);
            updateStatus("[server:] A client is now connected");
            } catch (Exception ex){
            }
            }
            

機(jī)器上的每臺(tái)藍(lán)牙設(shè)備都需要惟一的標(biāo)識(shí)符,所以我決定將這個(gè)服務(wù)的 UUID (統(tǒng)一惟一標(biāo)識(shí)符)定為 8841 (可以是任意四位數(shù)字)。在創(chuàng)建客戶機(jī)應(yīng)用程序時(shí)需要記住這個(gè) UUID。

因?yàn)檎趧?chuàng)建 JSR-82 服務(wù)器應(yīng)用程序,所以需要調(diào)用 Connector.open() 并傳遞進(jìn) String,其中包含服務(wù)的 URL。因?yàn)檫@是一個(gè) OBEX 應(yīng)用程序,所以采用的協(xié)議是 btgoep。而且,也可以看到服務(wù)被命名為 “FTP”(也可以取其他的名稱)。

FileServer.java 是一個(gè) OBEX 服務(wù)器應(yīng)用程序,這意味著 OBEX 客戶機(jī)將發(fā)送 OBEX 操作,例如 CONNECT、GET、PUT 等等。所以,類需要恰當(dāng)?shù)靥幚砜蛻魴C(jī)將要發(fā)送的每個(gè)操作(或者我想要處理的操作)。所以,在 FileServer.java 中,我包含了 onPut()、onConnect()onDisconnect() 方法的實(shí)現(xiàn)。我可能還創(chuàng)建了 onGet() 的實(shí)現(xiàn),但是因?yàn)橹幌霃目蛻魴C(jī)向服務(wù)器發(fā)送簡(jiǎn)單文件,所以實(shí)現(xiàn) onGet() 并不是必需的,而只需要實(shí)現(xiàn) onPut() 方法。

清單 3 演示了 onConnect()onDisconnect() 的實(shí)現(xiàn)??梢钥吹?,onConnect() 要求一個(gè) int 返回值,但是 onDisconnect() 不返回內(nèi)容,因?yàn)椴恍枰?


清單 3. FilesServer.onConnect() 和 FilesServer.onDisconnect()
            public int onConnect(HeaderSet request, HeaderSet reply) {
            updateStatus("[server:] The client has created an OBEX session");
            return ResponseCodes.OBEX_HTTP_OK;
            }
            public void onDisconnect (HeaderSet req, HeaderSet resp) {
            updateStatus("[server:] The client has disconnected the OBEX session");
            }
            

現(xiàn)在來(lái)看允許 FileServer.java 在客戶機(jī)發(fā)送 PUT 請(qǐng)求時(shí)從客戶機(jī)接收文件的代碼段。onPut() 的代碼如清單 4 所示。


清單 4. FilesServer.onPut()
            public int onPut (Operation op) {
            try {
            java.io.InputStream is = op.openInputStream();
            updateStatus("Got data bytes " + is.available() + " name "
            + op.getReceivedHeaders().getHeader(HeaderSet.NAME) +
            " type " + op.getType());
            File f =
            new File((String)op.getReceivedHeaders().getHeader(HeaderSet.NAME));
            FileOutputStream fos = new FileOutputStream (f);
            byte b[] = new byte[1000];
            int len;
            while (is.available() > 0 && (len = is.read(b)) > 0) {
            fos.write (b, 0, len);
            }
            fos.close();
            updateStatus("[server:] Wrote data to " + f.getAbsolutePath());
            } catch (Exception e) {
            e.printStackTrace();
            }
            return ResponseCodes.OBEX_HTTP_OK;
            }
            

正如我前面說(shuō)的,清單 4 的代碼顯示了 OBEX 服務(wù)器如何從遠(yuǎn)程藍(lán)牙設(shè)備接收文件。您可能會(huì)注意到可以得到傳輸?shù)奈募拿Q,在這個(gè)示例中,在實(shí)例化 File 對(duì)象時(shí)使用到了文件名稱。


結(jié)束語(yǔ)

在這篇文章中,我介紹了開(kāi)始創(chuàng)建使用 OBEX 協(xié)議的 Java 藍(lán)牙應(yīng)用程序的許多基礎(chǔ)知識(shí)。您學(xué)習(xí)了對(duì)于數(shù)據(jù)傳輸什么時(shí)候選擇 OBEX 比 RFCOMM 更合適。閱讀完這篇文章時(shí),您應(yīng)當(dāng)很好地掌握了 OBEX 應(yīng)用程序需要的語(yǔ)義的知識(shí)。

在這個(gè)系列的第 2 部分中,我將介紹如何創(chuàng)建能夠與這里創(chuàng)建的服務(wù)器應(yīng)用程序正確通信的客戶機(jī)應(yīng)用程序。當(dāng)您很好地理解了客戶機(jī)代碼之后,我將對(duì)客戶機(jī)代碼稍做修改,創(chuàng)建一個(gè)藍(lán)牙音樂(lè)商店。


參考資料

學(xué)習(xí)

  • 您可以參閱本文在 developerWorks 全球站點(diǎn)上的 英文原文。

  • Open OBEX Project 正在規(guī)劃 Object Exchange 協(xié)議的開(kāi)放源碼實(shí)現(xiàn),它是一個(gè)會(huì)話協(xié)議,用二進(jìn)制 HTTP 協(xié)議描述最合適。

  • PalmOS data collection series”(developerWorks,2001 年 11 月)探索了為無(wú)線設(shè)備開(kāi)發(fā)數(shù)據(jù)搜集應(yīng)用程序的關(guān)鍵部分。

獲得產(chǎn)品和技術(shù)

關(guān)于作者

Bruce Hopkins

Bruce Hopkins 是 Bluetooth for Java (Apress)的作者,也是 JB-22 開(kāi)發(fā)包的創(chuàng)建者。他畢業(yè)于底特律的 Wayne 州立大學(xué),擁有電子和計(jì)算機(jī)工程學(xué)士學(xué)位。他目前是 Gestalt LLC 的技術(shù)架構(gòu)師,專攻分布式計(jì)算、Web 服務(wù)和無(wú)線技術(shù)。您可以通過(guò)他的電子郵件 bhopkins@gestalt-llc.com 與他聯(lián)系。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多