成人午夜激情影院,小视频免费在线观看,国产精品夜夜嗨,欧美日韩精品一区二区在线播放

VB.NET利用OBEX協(xié)議實(shí)現(xiàn)紅外線文件傳輸

2010-08-28 10:48:10來(lái)源:西部e網(wǎng)作者:

  十一月開(kāi)始沒(méi)有做什么項(xiàng)目,每天站在在辦公室窗前靜靜地看著樓下的行人來(lái)來(lái)往往,然后等待著領(lǐng)工資的時(shí)刻。為了讓智慧的大腦不因無(wú)所事是而僵硬,我決定找點(diǎn)傷腦筋的事情來(lái)維持腦袋的正常運(yùn)轉(zhuǎn)。經(jīng)過(guò)考慮,決定用VB.net實(shí)現(xiàn)紅外線文件傳輸?shù)睦獭?BR>
  一、OBEX協(xié)議淺析

  目前的紅外線傳輸大都遵循OBEX協(xié)議,這是由微軟、蘋果、諾基亞等公司專門為紅外線傳輸而制定的一整套協(xié)議規(guī)則。最新協(xié)議版本是1.3版,在官方網(wǎng)站上下載要20美元(有錢的可以去下,我反正是玩玩,叫我交錢是不可能的,本文中實(shí)現(xiàn)的依據(jù)是在網(wǎng)上找到的OBEX協(xié)議1.2版本的文檔)。協(xié)議文檔的第二章OBEX Object Model是關(guān)鍵部份,實(shí)現(xiàn)文件傳輸必須對(duì)這章說(shuō)明仔細(xì)研究清楚。以下先就對(duì)這章的一些關(guān)鍵點(diǎn)進(jìn)行講解。

  1、OBEX協(xié)議的對(duì)象模型

  1)OBEX協(xié)議使用一系列的數(shù)據(jù)包(header)來(lái)進(jìn)行某種對(duì)象(通常是文件)的傳輸,其基本格式是這樣的:

  <Header ID>'數(shù)據(jù)包的標(biāo)識(shí)
  <Header Value> '數(shù)據(jù)包內(nèi)的數(shù)據(jù)

  其中<Header ID>是個(gè)單字節(jié)(八位二進(jìn)制)字符,這個(gè)字符的低六位標(biāo)識(shí)數(shù)據(jù)包代表的意義,高兩位表示這個(gè)數(shù)據(jù)包的總長(zhǎng)度的表達(dá)方式,如下表:

高倆位二進(jìn)制數(shù)據(jù) 意義
00 這個(gè)數(shù)據(jù)包的<header Value>是一個(gè)以空字符結(jié)尾的unicode字符串
01 這個(gè)數(shù)據(jù)包的<header Value>是一個(gè)以空字符結(jié)尾的單字節(jié)組成的字符串,<header Value>的前兩個(gè)字節(jié)數(shù)據(jù)組成的16位整數(shù)表示整個(gè)數(shù)據(jù)包的長(zhǎng)度(包括<header id>及<header value>的總長(zhǎng))
10 <header Value>的長(zhǎng)度只有一個(gè)字節(jié)數(shù)據(jù)
11 <header Value>的長(zhǎng)度只有四個(gè)字節(jié)數(shù)據(jù),并以網(wǎng)格數(shù)據(jù)格式排列(高位數(shù)據(jù)放在低位字節(jié)中存儲(chǔ))

  注意:在<header Value>的16位數(shù)據(jù)(如包的長(zhǎng)度、Unicode字符在發(fā)送方均要做高位字放在低位字發(fā)送的處理。由于沒(méi)注意這個(gè)問(wèn)題,我曾在開(kāi)頭的四五天時(shí)間里嘔血數(shù)升而一直沒(méi)有成功將數(shù)據(jù)發(fā)送成功)

  在應(yīng)用中,數(shù)據(jù)包可以嵌套。也就是:Header Value可以包含其它的數(shù)據(jù)包,所以長(zhǎng)度標(biāo)識(shí)非常重要,它可以幫助軟件的實(shí)現(xiàn)根據(jù)包的長(zhǎng)度迅速分離出包內(nèi)的數(shù)據(jù)。

  在本文實(shí)現(xiàn)中主要用到的數(shù)據(jù)包標(biāo)識(shí)如下(其余的項(xiàng)請(qǐng)參閱詳細(xì)官方協(xié)議):

  常用數(shù)據(jù)包標(biāo)識(shí)列表

十六進(jìn)制值 標(biāo)識(shí)名稱 標(biāo)識(shí)含義
0x01 Name 標(biāo)記對(duì)象的名稱(通常是文件的文件名)
0xC3 Length 以字節(jié)為單位計(jì)算的對(duì)象長(zhǎng)度
0x44 Time 時(shí)間(以ISO 8601規(guī)范為標(biāo)準(zhǔn))
0x480x49 BodyEnd of Body 標(biāo)識(shí)一個(gè)對(duì)象數(shù)據(jù)塊的開(kāi)始標(biāo)識(shí)這是對(duì)象的最后一個(gè)數(shù)據(jù)塊

  OBEX協(xié)議數(shù)據(jù)對(duì)象傳輸是按照服務(wù)器端/客戶端的方式進(jìn)行的,每個(gè)操作均提供一個(gè)操作碼以明確操作的含義。以下給出部分?jǐn)?shù)據(jù)發(fā)送所需操作碼列表:

0x80 Connect 標(biāo)識(shí)申請(qǐng)開(kāi)始一個(gè)對(duì)象傳輸會(huì)話,并可以在這個(gè)數(shù)據(jù)包中告知紅外接收方一些必要的兼容性信息。
0x81 Disconnect 標(biāo)識(shí)對(duì)象傳輸會(huì)話結(jié)束
0x020x82 PutFinal_Put 發(fā)送對(duì)象的put動(dòng)作(當(dāng)標(biāo)識(shí)為0x82時(shí)說(shuō)明這是最后的一個(gè)Put動(dòng)作)
0xA0 Success 說(shuō)明接收端已成功收到put動(dòng)作發(fā)送的所有數(shù)據(jù)(一般是在成功收到Final_Put標(biāo)識(shí)的數(shù)據(jù)包后的反饋)
0x90 Continue 說(shuō)明接收端已收到put動(dòng)作發(fā)送的數(shù)據(jù),因?yàn)镕inal_Put還沒(méi)出現(xiàn),所以要求發(fā)送端繼續(xù)發(fā)送數(shù)據(jù)。

  發(fā)送方和接收方是的通信的基本格式如下:

字節(jié)0 字節(jié)1,2 字節(jié)三以后的數(shù)據(jù)
操作碼 整個(gè)通信數(shù)據(jù)包的長(zhǎng)度 通訊的數(shù)據(jù)

  以下結(jié)合基本傳輸步驟,對(duì)上文列出的數(shù)據(jù)包使用方法進(jìn)行講解:

  1、由發(fā)送方向接收文件的接收方進(jìn)行連接請(qǐng)求。

  發(fā)送方需要使用的操作碼為Connect,在OBEX協(xié)議中對(duì)Connect數(shù)據(jù)包格式作如下規(guī)定:

字節(jié)0 字節(jié)1、2 字節(jié)3 字節(jié)4 字節(jié)5、6 字節(jié)7
Connect操作碼(0x80) Connect數(shù)據(jù)包的總長(zhǎng)度 OBEX協(xié)議的版本(目前為1.0,16進(jìn)制表示為0x10) 保留未用,設(shè)為0 最大可處理的OBEX包長(zhǎng)度 其它的數(shù)據(jù)包(可選)

  服務(wù)端根據(jù)連接的請(qǐng)求向客戶端做出響應(yīng):

字節(jié)0 字節(jié)1、2 字節(jié)3 字節(jié)4 字節(jié)5、6 字節(jié)7
響應(yīng)的操作碼 響應(yīng)數(shù)據(jù)包的總長(zhǎng)度 OBEX協(xié)議的版本(目前為1.0,16進(jìn)制表示為0x10) 保留未用,設(shè)為0 最大可處理的OBEX包長(zhǎng)度 其它的數(shù)據(jù)包(可選)

  如果接收方允許連接,響應(yīng)的操作碼會(huì)為Success(0xA0)其它的響應(yīng)操作碼均被認(rèn)為連接失敗。

  2、發(fā)送方向接收方發(fā)送數(shù)據(jù)

  發(fā)送方通過(guò)put和Final_Put這兩個(gè)操作將傳輸?shù)臄?shù)據(jù)信息向接收方發(fā)送。

  發(fā)送方的Put/Final_Put使用格式。

字節(jié)0 字節(jié)1,2 字節(jié)三以后的數(shù)據(jù)
Put操作碼(0x02)Final_Put操作碼(0x82) 整個(gè)通信數(shù)據(jù)包的長(zhǎng)度 通訊的數(shù)據(jù)(由其它的例如name/body等數(shù)據(jù)包構(gòu)成)

  當(dāng)最后一次傳輸對(duì)象的數(shù)據(jù)時(shí)要使用Final_Put告知接收方這是最后一個(gè)數(shù)據(jù)包了,以便接收方根據(jù)接收到的數(shù)據(jù)進(jìn)行處理(例如將接收到的文件存盤)。

  接收方的響應(yīng)格式:

字節(jié)0 字節(jié)1,2 字節(jié)三以后的數(shù)據(jù)
響應(yīng)操作碼典型的有兩個(gè)值:Success操作碼(0xA0)Continue操作碼(0x90 ) 整個(gè)通信數(shù)據(jù)包的長(zhǎng)度 通訊的數(shù)據(jù)(由其它的例如name/body等數(shù)據(jù)包構(gòu)成)

  如果接收方成功收到put操作的數(shù)據(jù),應(yīng)該返回Continue開(kāi)始的響應(yīng)信息,告知發(fā)送方繼續(xù)發(fā)送,在成功收到Final_Put發(fā)送的數(shù)據(jù)后,應(yīng)返回Success響應(yīng)信息,告知發(fā)送方整個(gè)對(duì)象都接收完成。(但由于部分適配器只會(huì)返回Success響應(yīng),出于兼容性考慮,在編程中應(yīng)理解為無(wú)論接收到Success或Continue響應(yīng)都代表數(shù)據(jù)發(fā)送成功。)

  3、發(fā)送方關(guān)閉連接

  發(fā)送方在最后應(yīng)以Disconnect信息明確結(jié)束連接,這并不是必須的,但推薦使用。

  發(fā)送方格式:

字節(jié)0 字節(jié)1,2 字節(jié)三以后的數(shù)據(jù)
Disconnect操作碼 整個(gè)通信數(shù)據(jù)包的長(zhǎng)度 可選的通訊的數(shù)據(jù)(由其它的數(shù)據(jù)包構(gòu)成)

  接收方響應(yīng):

字節(jié)0 字節(jié)1,2 字節(jié)三以后的數(shù)據(jù)
Success操作碼(0xA0)服務(wù)不可用操作碼(0xD3) 整個(gè)通信數(shù)據(jù)包的長(zhǎng)度 可選的通訊的數(shù)據(jù)(由其它的數(shù)據(jù)包構(gòu)成)


  當(dāng)成功斷開(kāi)時(shí),接收方會(huì)發(fā)送Success信息。否則,如果發(fā)送方的disconnect操作包含錯(cuò)誤信息(例如一個(gè)錯(cuò)誤的連接ID)時(shí),會(huì)返加0xD3操作碼。但并不能操作所有接收方的程序都實(shí)現(xiàn)這個(gè)響應(yīng)的功能,也就是說(shuō),發(fā)送方并不能保證一定會(huì)得到響應(yīng)信息。

  二、程序?qū)崿F(xiàn)

  .net1.0中對(duì)紅外的支持全部在System.Net.Sockets空間中,使用很簡(jiǎn)單,和普通的網(wǎng)絡(luò)連接差不多,主要有三個(gè)類:

IrDAClient 提供連接信息,并創(chuàng)建客戶端連接對(duì)象,用以打開(kāi)和關(guān)閉與服務(wù)器的連接。
IrDADeviceInfo 提供客戶端在發(fā)現(xiàn)查詢過(guò)程中獲取的有關(guān)可用服務(wù)器和端口的信息。
IrDAListener 將套接字置于偵聽(tīng)狀態(tài),以監(jiān)視來(lái)自指定服務(wù)或網(wǎng)絡(luò)地址的連接。
  
  (一)、獲取附近可用紅外設(shè)備的信息

  在這個(gè)示例中,我獲取紅外設(shè)備通過(guò)IrDAClient的DiscoverDevices方法實(shí)現(xiàn),該方法以IrDADeviceInfo類型的對(duì)象數(shù)組返回附近可用紅外設(shè)備的相關(guān)信息。這個(gè)方法唯一的參數(shù)表示如果附近有許多紅外設(shè)備時(shí),最多收集多少個(gè)設(shè)備的信息。

  示例代碼如下:

Dim taobjIrDADeviceInfo() As Sockets.IrDADeviceInfo
Dim tobjIrDAClient As New Sockets.IrDAClient
'開(kāi)始檢索附近的紅外設(shè)備并加入到列表中,最多只搜索7個(gè)設(shè)備
taobjIrDADeviceInfo = tobjIrDAClient.DiscoverDevices(7)

  在得到的IrDADeviceInfo類型的變量有三個(gè)有用的屬性,你可根據(jù)這些屬性的值給用戶提示,以便由用戶選擇應(yīng)連接到那一個(gè)紅外設(shè)備上:

  DeviceID 獲取紅外設(shè)備標(biāo)識(shí)符,在連接紅外設(shè)備中使用

  DeviceName 獲取紅設(shè)備名稱。

  Hints 獲取設(shè)備的類型,例如是紅外手機(jī)還是紅外PDA之類的說(shuō)明

  (二)、用IrDAClient對(duì)象實(shí)現(xiàn)紅外連接及數(shù)據(jù)發(fā)送

  IrDAClient和一般的網(wǎng)絡(luò)連接對(duì)象的使用很相似,使用的基本步驟如下:

  1)、先使用connect方法連接指定的紅外設(shè)備,這個(gè)方法需要一個(gè)IrDAEndPoint對(duì)象作為參數(shù)(這個(gè)對(duì)象指定需連接的紅外設(shè)備,以及連接到紅外設(shè)備提供的指定服務(wù)上)

  示例:

Dim tobjIrDAClient As New Sockets.IrDAClient
'ni_objIrDADeviceInfo是上文介紹的IrDADeviceInfo對(duì)象,以下語(yǔ)句的含義就是連接到'DeviceID指定的紅外設(shè)備上,這個(gè)設(shè)備提供OBEX服務(wù)。
Dim tobjIrDAEndPoint As New IrDAEndPoint(ni_objIrDADeviceInfo.DeviceID, "OBEX")
Try
tobjIrDAClient.Connect(tobjIrDAEndPoint)
Catch ex As Exception
MessageBox.Show("IrDA Socket Connect 狀態(tài)失敗")
End Try

  2)、連接成功后就可以使用IrDAClient對(duì)象的GetStream 方法獲得基礎(chǔ)數(shù)據(jù)流,并利用流Read/Write方法實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)慕邮?發(fā)送。

  示例:兩個(gè)方法的第一個(gè)參數(shù)都是一個(gè)字節(jié)數(shù)組

  數(shù)據(jù)發(fā)送:tobjIrDAClient.GetStream.Write(tabytTempa, 0, tabytTempa.Length)

  數(shù)據(jù)接收:tobjIrDAClient.GetStream.Read(tabytReceiveBuffer, 0, 7)

  3)、完成所有通信后使用流以及IrDAClient的Close方法 關(guān)閉連接。

  示例:tobjIrDAClient.GetStream.Close()
     tobjIrDAClient.Close()

  (三)完整實(shí)現(xiàn)代碼

  其實(shí)紅外操作在net中實(shí)現(xiàn)就是這么簡(jiǎn)單,不過(guò)困難的是對(duì)OBEX協(xié)議的解釋,基于代碼重用的原則,我的程序主框架有兩個(gè)基礎(chǔ)類,clsIrDAOBEXOperator封裝了文件發(fā)送的方法,方法中調(diào)用另一個(gè)類clsOBEXHeaders,這個(gè)類主門用來(lái)構(gòu)建obex協(xié)議需要的數(shù)據(jù)包。代碼如下,其中已包括必要的注釋:

  clsIrDAOBEXOperator.vb的代碼(代碼中fnSendFileToIrDADevice是向紅外設(shè)備發(fā)送文件的方法,它的第一個(gè)參數(shù)是代表紅外設(shè)備的IrDADeviceInfo對(duì)象,第二個(gè)參數(shù)就是要發(fā)送的文件名),:

Imports System.Net
Imports System.Net.Sockets

Public Class clsIrDAOBEXOperator
'OBEX常數(shù)
Public Const cOBEX_VERSION As Byte = &H10
Public Const cOBEX_CONNECTFLAGS As Byte = &H0

Public Const cOBEX_CONNECT As Byte = &H80
Public Const cOBEX_DISCONNECT As Byte = &H81
Public Const cOBEX_PUT As Byte = &H2
Public Const cOBEX_NAME As Byte = &H1
Public Const cOBEX_PUT_FINAL As Byte = &H82
Public Const cOBEX_LENGTH As Byte = &HC3
Public Const cOBEX_BODY As Byte = &H48
Public Const cOBEX_END_OF_BODY As Byte = &H49

Public Const cOBEX_CONTINUE As Byte = &H90
Public Const cOBEX_SUCCESS As Byte = &HA0


'向外界公布可直接修改的變量
Public m_i32OBEXMAXSendBufferLen As Int32 = 255
Public m_i32OBEXMAXReceiveBufferLen As Int32 = 1024
Public m_i32OBEXMAXPacketSize As Int16 = &H808

'將一個(gè)16位整數(shù)轉(zhuǎn)為2個(gè)字節(jié)的數(shù)組,并存入?yún)?shù)中指定索引開(kāi)始的字節(jié)數(shù)組處(低位字在低字節(jié),高位字在高字節(jié))
Private Function fnInt16ToByteArray(ByVal ni_i16Convert As Int16, ByRef ni_abytDest() As Byte, ByVal ni_i32StartIndex As Int32) As Boolean
ni_abytDest(ni_i32StartIndex) = ni_i16Convert And &HFF
ni_abytDest(ni_i32StartIndex + 1) = ni_i16Convert >> 8

End Function

'將一個(gè)16位整數(shù)轉(zhuǎn)為2個(gè)字節(jié)的數(shù)組,并存入?yún)?shù)中指定索引開(kāi)始的字節(jié)數(shù)組處
Private Function fnInt16ToByteArrayLowByteToHightPosition(ByVal ni_i16Convert As Int16, ByRef ni_abytDest() As Byte, ByVal ni_i32StartIndex As Int32) As Boolean
ni_abytDest(ni_i32StartIndex + 1) = ni_i16Convert And &HFF
ni_abytDest(ni_i32StartIndex) = ni_i16Convert >> 8

End Function

'將一個(gè)32位整數(shù)轉(zhuǎn)為4個(gè)字節(jié)的數(shù)組,并存入?yún)?shù)中指定索引開(kāi)始的字節(jié)數(shù)組處
Private Function fnInt32ToByteArrayLowByteToHightPosition(ByVal ni_i32Convert As Int16, ByRef ni_abytDest() As Byte, ByVal ni_i32StartIndex As Int32) As Boolean
Dim ti32Tempa As Int32 = ni_i32Convert
ni_abytDest(ni_i32StartIndex + 3) = ni_i32Convert And &HFF
ni_abytDest(ni_i32StartIndex + 2) = (ni_i32Convert And &HFF00) >> 8
ni_abytDest(ni_i32StartIndex + 1) = (ni_i32Convert And &HFF0000) >> 16
ni_abytDest(ni_i32StartIndex) = (ti32Tempa And &HFF000000) >> 24

End Function


'將本設(shè)備中指定的文件傳到指定的設(shè)備中去
Public Function fnSendFileToIrDADevice(ByVal ni_objIrDADeviceInfo As IrDADeviceInfo, _
ByVal ni_strFilePath As String) As Boolean
'ni_objIrDADeviceInfo:指定紅外設(shè)備的IrDAInfo結(jié)構(gòu)
'ni_strFilePath:要傳輸?shù)奈募窂?BR>'返回值:成功返回true

Dim tobjIrDAClient As New Sockets.IrDAClient
Dim tobjIrDAEndPoint As New IrDAEndPoint(ni_objIrDADeviceInfo.DeviceID, "OBEX")
Dim tabytSendBuffer(m_i32OBEXMAXSendBufferLen * 2) As Byte
Dim tabytReceiveBuffer(m_i32OBEXMAXReceiveBufferLen) As Byte
Dim tblnTemp As Boolean
Dim ti32Tempa As Int32, ti32TempB As Int32, tieTempC As Int32
Dim tbytTempa As Byte
Dim ti32LoopA As Int32
Dim tobjBinaryReader As IO.BinaryReader
Dim tobjFileStream As IO.FileStream
Dim tabytTempa() As Byte, tabytTempb() As Byte, tabytTempC() As Byte, tabytTempD() As Byte
Dim tabytTempE() As Byte
Dim tobjOBEX_HEADERS As New clsOBEXHeaders
Dim ti32SendPackageSpare As Int32 '保存最大發(fā)送包數(shù)組-當(dāng)前數(shù)據(jù)后的剩余空間
Dim tobjFileInfo As IO.FileInfo

tobjFileInfo = New IO.FileInfo(ni_strFilePath)

Try

Try
tobjIrDAClient.Connect(tobjIrDAEndPoint)

Catch ex As Exception
MessageBox.Show("IrDA Socket Connect 狀態(tài)失敗")
Return False
End Try

'創(chuàng)建一個(gè)最簡(jiǎn)單的連接信息
tabytTempa = tobjOBEX_HEADERS.fnCreateConnectHeaderRequest(, , , m_i32OBEXMAXPacketSize)

Try
tobjIrDAClient.GetStream.Write(tabytTempa, 0, tabytTempa.Length)
tobjIrDAClient.GetStream.Flush()

Catch ex As Exception
MessageBox.Show("OBEX_CONNECT信息發(fā)送失敗")
Application.DoEvents()
Return False
End Try

If tobjIrDAClient.GetStream.CanRead = True Then
Try
tobjIrDAClient.GetStream.Read(tabytReceiveBuffer, 0, 7)

Catch ex As Exception
MessageBox.Show("接收OBEX_CONNECT響應(yīng)消息失敗")
Return False
End Try

If tabytReceiveBuffer(0) <> cOBEX_SUCCESS Then
MessageBox.Show("OBEX_CONNECT沒(méi)接收到相應(yīng)的響應(yīng)")
Return False
End If

End If

'發(fā)送put包
'Name包
tabytTempa = tobjOBEX_HEADERS.fnCreateNameHeader(IO.Path.GetFileName(ni_strFilePath))
ti32Tempa = tabytTempa.Length

'lenght包
tabytTempb = tobjOBEX_HEADERS.fnCreateLengthHeader(tobjFileInfo.Length)
ti32TempB = tabytTempb.Length


'時(shí)間
tabytTempC = tobjOBEX_HEADERS.fnCreateTimeHeaderISO(Now)

ReDim Preserve tabytTempa(tabytTempa.Length + tabytTempb.Length + tabytTempC.Length)

tabytTempb.CopyTo(tabytTempa, ti32Tempa)
tabytTempC.CopyTo(tabytTempa, ti32Tempa + ti32TempB)
tabytTempa = tobjOBEX_HEADERS.fnCreatePutHeader(tabytTempa)

'將名稱、時(shí)間、文件長(zhǎng)度等基本信息先發(fā)出去
Try
tobjIrDAClient.GetStream.Write(tabytTempa, 0, tabytTempa.Length)
Catch ex As Exception
Return False
End Try

Try
tobjIrDAClient.GetStream.Read(tabytReceiveBuffer, 0, tabytReceiveBuffer.Length)
Catch ex As Exception
'接收服務(wù)器端響應(yīng)時(shí)失敗
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False

End Try

If tabytReceiveBuffer(0) <> cOBEX_SUCCESS And tabytReceiveBuffer(0) <> cOBEX_CONTINUE Then
'沒(méi)有收到服務(wù)器的對(duì)應(yīng)的響應(yīng)信息
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False
End If


'開(kāi)始正式發(fā)送文件的數(shù)據(jù)
Try
tobjFileStream = IO.File.Open(ni_strFilePath, IO.FileMode.Open, IO.FileAccess.Read)
tobjBinaryReader = New IO.BinaryReader(tobjFileStream)

Catch ex As Exception
MessageBox.Show("打開(kāi)文件時(shí)出現(xiàn)錯(cuò)誤")
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False
End Try

'讀出文件的數(shù)據(jù)放到body中,總長(zhǎng)度必須少于最大發(fā)送長(zhǎng)度-put標(biāo)志的3字節(jié)-body標(biāo)志的3字節(jié)
'最多可發(fā)送的文件信息長(zhǎng)度
ti32SendPackageSpare = m_i32OBEXMAXSendBufferLen - 6

'循環(huán)讀取文件的內(nèi)容,并發(fā)送到服務(wù)方
For ti32LoopA = 1 To Math.Ceiling(tobjFileInfo.Length / ti32SendPackageSpare)
Try
tabytTempa = tobjBinaryReader.ReadBytes(ti32SendPackageSpare)
Catch ex As Exception
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False
End Try

'構(gòu)建合適的put包并發(fā)送
tabytTempb = tobjOBEX_HEADERS.fnCreateBodyHeader(tabytTempa) 'body標(biāo)志
tabytTempa = tobjOBEX_HEADERS.fnCreatePutHeader(tabytTempb)

'開(kāi)始發(fā)送
Try
tobjIrDAClient.GetStream.Write(tabytTempa, 0, tabytTempa.Length)
tobjIrDAClient.GetStream.Flush()

Catch ex As Exception
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False
End Try

Try
tobjIrDAClient.GetStream.Read(tabytReceiveBuffer, 0, tabytReceiveBuffer.Length)
Catch ex As Exception
'接收服務(wù)器端響應(yīng)時(shí)失敗
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False

End Try

If tabytReceiveBuffer(0) <> cOBEX_SUCCESS And tabytReceiveBuffer(0) <> cOBEX_CONTINUE Then
'沒(méi)有收到服務(wù)器的對(duì)應(yīng)的響應(yīng)信息
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False
End If

Next

'關(guān)閉文件
tobjBinaryReader.Close()
tobjFileStream.Close()

If ti32Tempa Then

End If
'文件數(shù)據(jù)已全部發(fā)送完畢,發(fā)送結(jié)束的final_put 包
'endbody包
tabytTempa = tobjOBEX_HEADERS.fnCreateEndOfBodyHeader(Nothing)
'putfinal
tabytTempa = tobjOBEX_HEADERS.fnCreatePut_FinalHeaderResponse(tabytTempa)
Try
tobjIrDAClient.GetStream.Write(tabytTempa, 0, tabytTempa.Length)
tobjIrDAClient.GetStream.Flush()
Catch ex As Exception
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False
End Try


Try
tobjIrDAClient.GetStream.Read(tabytReceiveBuffer, 0, tabytReceiveBuffer.Length)
Catch ex As Exception
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False
End Try

If tabytReceiveBuffer(0) <> cOBEX_SUCCESS Then
'沒(méi)有收到服務(wù)器的對(duì)應(yīng)的響應(yīng)信息
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False
End If

'發(fā)送disconnect包
tabytTempa = tobjOBEX_HEADERS.fnCreateDisConnectHeaderRequest()
Try
tobjIrDAClient.GetStream.Write(tabytTempa, 0, tabytTempa.Length)
tobjIrDAClient.GetStream.Flush()
Catch ex As Exception
tobjIrDAClient.GetStream.Close()
tobjIrDAClient.Close()
Return False
End Try

tobjIrDAClient.Close()

Catch ex As Exception
MessageBox.Show("過(guò)程發(fā)生不明錯(cuò)誤")
Return False
End Try


'代碼能來(lái)到這兒就是正常完成任務(wù)了
MsgBox("紅外操作成功")
Return True

End Function
End Class
clsOBEXHeaders.vb文件的代碼:
Public Class clsOBEXHeaders
#Region "OBEX常數(shù)"
Public Const cOBEX_VERSION As Byte = &H10
Public Const cOBEX_CONNECTFLAGS As Byte = &H0

Public Const cOBEX_CONNECT As Byte = &H80
Public Const cOBEX_DISCONNECT As Byte = &H81
Public Const cOBEX_PUT As Byte = &H2
Public Const cOBEX_NAME As Byte = &H1
Public Const cOBEX_PUT_FINAL As Byte = &H82
Public Const cOBEX_LENGTH As Byte = &HC3
Public Const cOBEX_BODY As Byte = &H48
Public Const cOBEX_END_OF_BODY As Byte = &H49
Public Const cOBEX_TIME_ISO As Byte = &H44

Public Const cOBEX_CONTINUE As Byte = &H90
Public Const cOBEX_SUCCESS As Byte = &HA0

#End Region

#Region "類內(nèi)私有函數(shù)"

'將一個(gè)16位整數(shù)轉(zhuǎn)為2個(gè)字節(jié)的數(shù)組,并存入?yún)?shù)中指定索引開(kāi)始的字節(jié)數(shù)組處
Private Sub sbInt16ToByteArrayLowByteToHightPosition(ByVal ni_i16Convert As Int16, ByRef ni_abytDest() As Byte, ByVal ni_i32StartIndex As Int32)

ni_abytDest(ni_i32StartIndex + 1) = ni_i16Convert And &HFF
ni_abytDest(ni_i32StartIndex) = ni_i16Convert >> 8

End Sub

''將一個(gè)16位整數(shù)轉(zhuǎn)為2個(gè)字節(jié)的數(shù)組,高位字放入高字節(jié),并存入?yún)?shù)中指定索引開(kāi)始的字節(jié)數(shù)組處
'Private Sub sbInt16ToByteArrayHightByteToHightPosition(ByVal ni_i16Convert As Int16, ByRef ni_abytDest() As Byte, ByVal ni_i32StartIndex As Int32)

' ni_abytDest(ni_i32StartIndex) = ni_i16Convert And &HFF
' ni_abytDest(ni_i32StartIndex + 1) = ni_i16Convert >> 8

'End Sub

'將一個(gè)32位整數(shù)轉(zhuǎn)為4個(gè)字節(jié)的數(shù)組,并存入?yún)?shù)中指定索引開(kāi)始的字節(jié)數(shù)組處
Private Sub sbInt32ToByteArrayLowByteToHightPosition(ByVal ni_i32Convert As Int16, ByRef ni_abytDest() As Byte, ByVal ni_i32StartIndex As Int32)

Dim ti32Tempa As Int32 = ni_i32Convert
ni_abytDest(ni_i32StartIndex + 3) = ni_i32Convert And &HFF
ni_abytDest(ni_i32StartIndex + 2) = (ni_i32Convert And &HFF00) >> 8
ni_abytDest(ni_i32StartIndex + 1) = (ni_i32Convert And &HFF0000) >> 16
ni_abytDest(ni_i32StartIndex) = (ti32Tempa And &HFF000000) >> 24

End Sub

#End Region

'創(chuàng)建一個(gè)新的ConnectHeader客戶端請(qǐng)求信息
Public Function fnCreateConnectHeaderRequest(Optional ByVal ni_abytOtherHeaders As Byte() = Nothing, _
Optional ByVal ni_bytOBEX_Version As Byte = cOBEX_VERSION, _
Optional ByVal ni_bytFlags As Byte = cOBEX_CONNECTFLAGS, _
Optional ByVal ni_i16MaxPacketLength As Int16 = 255) As Byte()
Dim tabytFuncReturn() As Byte


If Not (ni_abytOtherHeaders Is Nothing) Then
ReDim tabytFuncReturn(7 + ni_abytOtherHeaders.Length - 1)
Else
ReDim tabytFuncReturn(6)
End If

tabytFuncReturn(0) = cOBEX_CONNECT
tabytFuncReturn(3) = ni_bytOBEX_Version
tabytFuncReturn(4) = ni_bytFlags
sbInt16ToByteArrayLowByteToHightPosition(ni_i16MaxPacketLength, tabytFuncReturn, 5)

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入connect包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(7, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 7)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + 7, tabytFuncReturn, 1)
End If

Return tabytFuncReturn

End Function

'創(chuàng)建一個(gè)新的ConnectHeader的服務(wù)器端響應(yīng)信息數(shù)據(jù)
Public Function fnCreateConnectHeaderResponse(Optional ByVal ni_abytOtherHeaders As Byte() = Nothing, _
Optional ByVal ni_bytOBEX_Version As Byte = cOBEX_VERSION, _
Optional ByVal ni_bytFlags As Byte = cOBEX_CONNECTFLAGS, _
Optional ByVal ni_i16MaxPacketLength As Int16 = 255) As Byte()
Dim tabytFuncReturn() As Byte


If Not (ni_abytOtherHeaders Is Nothing) Then
ReDim tabytFuncReturn(7 + ni_abytOtherHeaders.Length - 1)
Else
ReDim tabytFuncReturn(6)
End If

tabytFuncReturn(0) = cOBEX_SUCCESS
tabytFuncReturn(3) = ni_bytOBEX_Version
tabytFuncReturn(4) = ni_bytFlags
sbInt16ToByteArrayLowByteToHightPosition(ni_i16MaxPacketLength, tabytFuncReturn, 5)

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入connect包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(7, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 7)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + 7, tabytFuncReturn, 1)
End If

Return tabytFuncReturn

End Function


'創(chuàng)建一個(gè)新的DisConnectHeader客戶請(qǐng)求信息
Public Function fnCreateDisConnectHeaderRequest(Optional ByVal ni_abytOtherHeaders As Byte() = Nothing) As Byte()
Dim tabytFuncReturn() As Byte


If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + ni_abytOtherHeaders.Length - 1)
Else
ReDim tabytFuncReturn(2)
End If

tabytFuncReturn(0) = cOBEX_DISCONNECT

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(3, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + 3, tabytFuncReturn, 1)
End If

Return tabytFuncReturn

End Function

'創(chuàng)建一個(gè)新的ContinueHeader信息
Public Function fnCreateContinueHeaderResponse(Optional ByVal ni_abytOtherHeaders As Byte() = Nothing) As Byte()
Dim tabytFuncReturn() As Byte


If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + ni_abytOtherHeaders.Length - 1)
Else
ReDim tabytFuncReturn(2)
End If

tabytFuncReturn(0) = cOBEX_CONTINUE

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(3, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + 3, tabytFuncReturn, 1)
End If

Return tabytFuncReturn

End Function

'創(chuàng)建一個(gè)新的SuccessHeader信息
Public Function fnCreateSuccessHeaderResponse(Optional ByVal ni_abytOtherHeaders As Byte() = Nothing) As Byte()
Dim tabytFuncReturn() As Byte


If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + ni_abytOtherHeaders.Length - 1)
Else
ReDim tabytFuncReturn(2)
End If

tabytFuncReturn(0) = cOBEX_SUCCESS

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(3, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + 3, tabytFuncReturn, 1)
End If

Return tabytFuncReturn

End Function

'創(chuàng)建一個(gè)新的TimeHeader信息
Public Function fnCreateTimeHeaderISO(ByVal ni_dtmDate As Date, Optional ByVal ni_abytOtherHeaders As Byte() = Nothing) As Byte()
Dim tabytFuncReturn() As Byte
Dim tstrDate As String
Dim tabytTempa() As Byte

'tstrDate = ni_dtmDate.Year & "." & ni_dtmDate.Month & "." & ni_dtmDate.Day & "T" & _
' ni_dtmDate.Hour & ":" & ni_dtmDate.Minute & ":" & ni_dtmDate.Second & "Z" & ControlChars.NullChar

tstrDate = String.Format("{0:yyyy/MM/dd\THH:mm:ss\Z}", ni_dtmDate) & ControlChars.NullChar
tabytTempa = Text.Encoding.BigEndianUnicode.GetBytes(tstrDate)


If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + tabytTempa.Length + ni_abytOtherHeaders.Length - 1)
Else
ReDim tabytFuncReturn(2 + tabytTempa.Length)
End If

tabytFuncReturn(0) = cOBEX_TIME_ISO

tabytTempa.CopyTo(tabytFuncReturn, 3) '將時(shí)間字節(jié)串放入返回?cái)?shù)組中

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(3 + tabytTempa.Length, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + 3 + tabytTempa.Length, tabytFuncReturn, 1)
End If

Return tabytFuncReturn


End Function

'創(chuàng)建一個(gè)新的BodyHeader信息
Public Function fnCreateBodyHeader(ByVal ni_abytBodyContent() As Byte, Optional ByVal ni_abytOtherHeaders As Byte() = Nothing) As Byte()
Dim tabytFuncReturn() As Byte
Dim tabytTempa As Byte
Dim ti32BodyContentLength As Int32 = 0


'定義合適大小的數(shù)組以容納bodyheader的內(nèi)容
If Not (ni_abytBodyContent Is Nothing) Then '有body的內(nèi)容
If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + ni_abytBodyContent.Length + ni_abytOtherHeaders.Length - 1)
ni_abytBodyContent.CopyTo(tabytFuncReturn, 3)
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, ni_abytBodyContent.Length + 3)
Else
ReDim tabytFuncReturn(2 + ni_abytBodyContent.Length)
ni_abytBodyContent.CopyTo(tabytFuncReturn, 3)
End If

Else '沒(méi)有body的內(nèi)容
If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + ni_abytOtherHeaders.Length - 1)
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)

Else
ReDim tabytFuncReturn(2)
End If

End If

tabytFuncReturn(0) = cOBEX_BODY

'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(tabytFuncReturn.Length, tabytFuncReturn, 1)

Return tabytFuncReturn


End Function

'創(chuàng)建一個(gè)新的EndOfBodyHeader信息
Public Function fnCreateEndOfBodyHeader(ByVal ni_abytBodyContent() As Byte, Optional ByVal ni_abytOtherHeaders As Byte() = Nothing) As Byte()
Dim tabytFuncReturn() As Byte
Dim tabytTempa As Byte
Dim ti32BodyContentLength As Int32 = 0


If Not (ni_abytBodyContent Is Nothing) Then
If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + ni_abytBodyContent.Length + ni_abytOtherHeaders.Length - 1)
ni_abytBodyContent.CopyTo(tabytFuncReturn, 3)
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3 + ni_abytBodyContent.Length)
Else
ReDim tabytFuncReturn(2 + ni_abytBodyContent.Length)
ni_abytBodyContent.CopyTo(tabytFuncReturn, 3)
End If

Else '沒(méi)有body內(nèi)容
If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + ni_abytOtherHeaders.Length - 1)
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)

Else
ReDim tabytFuncReturn(2)
End If

End If

'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(tabytFuncReturn.Length, tabytFuncReturn, 1)

tabytFuncReturn(0) = cOBEX_END_OF_BODY

Return tabytFuncReturn


End Function

'創(chuàng)建一個(gè)新的LengthHeader信息
Public Function fnCreateLengthHeader(ByVal ni_i32Length As Int32) As Byte()
Dim tabytFuncReturn() As Byte

ReDim tabytFuncReturn(4)

tabytFuncReturn(0) = cOBEX_LENGTH

'加入包的內(nèi)容
Call sbInt32ToByteArrayLowByteToHightPosition(ni_i32Length, tabytFuncReturn, 1)

Return tabytFuncReturn

End Function

'創(chuàng)建一個(gè)新的NameHeader信息
Public Function fnCreateNameHeader(ByVal ni_strName As String, Optional ByVal ni_abytOtherHeaders As Byte() = Nothing) As Byte()
Dim tabytFuncReturn() As Byte
Dim tabytTempa() As Byte
Dim ti32BodyContentLength As Int32 = 0


tabytTempa = Text.Encoding.BigEndianUnicode.GetBytes(ni_strName & ControlChars.NullChar)


If ni_strName <> "" Then
If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + tabytTempa.Length + ni_abytOtherHeaders.Length - 1)
Else '沒(méi)有其它數(shù)據(jù)包附后
ReDim tabytFuncReturn(2 + tabytTempa.Length)
End If

Else
If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面

ReDim tabytFuncReturn(3 + ni_abytOtherHeaders.Length - 1)
Else
ReDim tabytFuncReturn(2)
End If

End If



tabytFuncReturn(0) = cOBEX_NAME

If ni_strName <> "" Then

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(3 + tabytTempa.Length, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + tabytTempa.Length + 3, tabytFuncReturn, 1)
End If
tabytTempa.CopyTo(tabytFuncReturn, 3)

Else '沒(méi)有實(shí)際的body數(shù)據(jù)

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(3, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + 3, tabytFuncReturn, 1)
End If

End If

Return tabytFuncReturn

End Function

'創(chuàng)建一個(gè)新的PutHeader信息
Public Function fnCreatePutHeader(Optional ByVal ni_abytOtherHeaders As Byte() = Nothing) As Byte()
Dim tabytFuncReturn() As Byte


If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + ni_abytOtherHeaders.Length - 1)
Else
ReDim tabytFuncReturn(2)
End If

tabytFuncReturn(0) = cOBEX_PUT

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(3, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + 3, tabytFuncReturn, 1)
End If

Return tabytFuncReturn

End Function

'創(chuàng)建一個(gè)新的PutHeader信息
Public Function fnCreatePut_FinalHeaderResponse(Optional ByVal ni_abytOtherHeaders As Byte() = Nothing) As Byte()
Dim tabytFuncReturn() As Byte


If Not (ni_abytOtherHeaders Is Nothing) Then '有其它的數(shù)據(jù)包要附在后面
ReDim tabytFuncReturn(3 + ni_abytOtherHeaders.Length - 1)
Else
ReDim tabytFuncReturn(2)
End If

tabytFuncReturn(0) = cOBEX_PUT_FINAL

If ni_abytOtherHeaders Is Nothing Then '沒(méi)有其它的頭信息了
'加入包的長(zhǎng)度
Call sbInt16ToByteArrayLowByteToHightPosition(3, tabytFuncReturn, 1)
Else '還有其它頭信息
ni_abytOtherHeaders.CopyTo(tabytFuncReturn, 3)
Call sbInt16ToByteArrayLowByteToHightPosition(ni_abytOtherHeaders.Length + 3, tabytFuncReturn, 1)
End If

Return tabytFuncReturn

End Function

End Class

  以上代碼均為VB.net 2003編寫,在我的多普達(dá)515手機(jī)加紅外適配器上測(cè)試通過(guò),不過(guò)紅外傳輸是一個(gè)相對(duì)比較專業(yè)的課題,我的代碼并不是足夠健壯和可靠,希望對(duì)這方面有研究的朋友與我探討。我的QQ:85403578,郵箱:missilecat@163.com。

關(guān)鍵詞:.NETOBEX紅外線
主站蜘蛛池模板: 札达县| 虹口区| 宜君县| 临朐县| 文成县| 贡觉县| 库伦旗| 榕江县| 晋城| 金湖县| 全椒县| 永丰县| 章丘市| 宜州市| 都昌县| 庐江县| 偃师市| 信宜市| 三原县| 洛宁县| 阿鲁科尔沁旗| 克拉玛依市| 成武县| 农安县| 长葛市| 雷州市| 嘉峪关市| 连城县| 当阳市| 奎屯市| 甘肃省| 韶关市| 特克斯县| 新营市| 修水县| 常山县| 乌鲁木齐市| 兴安县| 南昌县| 玉门市| 当雄县|