C# 在PC上的通过蓝牙(bluetooth)发送数据到手机

概述

在PC端用.NET开发一个蓝牙下载的程序。实现在PC上查找周围的蓝牙设备(主要是手机),并将PC上的文件通过蓝牙传输到手机上。目前我采用的是OpenNETCF.Net.Bluetooth,能够正常发现周围的蓝牙设备,手机也能够正常进行蓝牙连接并接收文件。

代码实现

1、查找周围蓝牙设备

  1. BluetoothClient bc = new BluetoothClient();
  2. BluetoothDeviceInfo[] bdi;
  3. bdi = bc.DiscoverDevices(10);//查找周围最多10个蓝牙设备
  4. if (bdi.Length == 0)
  5. {
  6. this.ShowErrMsg("请确认您的蓝牙已开启!");
  7. return;
  8. }

2、打开数据流

  1. #region OBEXOpenStream
  2. public bool OBEXOpenStream(string BTMAC)
  3. {
  4. // serial port UUID
  5. Guid spguid = OpenNETCF.Net.Bluetooth.BluetoothService.ObexObjectPush;
  6. OpenNETCF.Net.BluetoothAddress btaddress = OpenNETCF.Net.BluetoothAddress.Parse(BTMAC);
  7. client = new OpenNETCF.Net.Sockets.BluetoothClient();
  8. // define endpoint
  9. OpenNETCF.Net.BluetoothEndPoint endpoint = new OpenNETCF.Net.BluetoothEndPoint(btaddress, spguid);
  10. try
  11. {
  12. //open socket
  13. client.Connect(endpoint);
  14. }
  15. catch
  16. {
  17. //unable to connect (server not listening on spguid)
  18. return false;
  19. }
  20. //connect socket
  21. stream = client.GetStream();
  22. return true;
  23. }
  24. #endregion

3、配对连接

  1. private bool OBEXConnect()
  2. {
  3. //send client request
  4. byte[] ConnectPacket = new byte[7];
  5. ConnectPacket[0] = 0x80; // Connect
  6. ConnectPacket[1] = 0x00; // Packetlength Hi Byte
  7. ConnectPacket[2] = 0x07; // Packetlength Lo Byte
  8. ConnectPacket[3] = 0x10; // Obex v1
  9. ConnectPacket[4] = 0x00; // no flags
  10. ConnectPacket[5] = 0x20; // 8k max packet size Hi Byte
  11. ConnectPacket[6] = 0x00; // 8k max packet size Lo Byte
  12. stream.Write(ConnectPacket, 0, ConnectPacket.Length);
  13. //listen for server response
  14. byte[] ReceiveBufferA = new byte[3];
  15. stream.Read(ReceiveBufferA, 0, 3);
  16. if (ReceiveBufferA[0] == 160) // 0xa0
  17. {
  18. //success, decode rest of packet
  19. int plength = (0xff * ReceiveBufferA[1]) + ReceiveBufferA[2]; //length of packet is...
  20. //listen for rest of packet
  21. byte[] ReceiveBufferB = new byte[plength - 3];
  22. stream.Read(ReceiveBufferB, 0, plength - 3);
  23. int obver = ReceiveBufferB[0]; //server obex version (16 = v1.0)
  24. int cflags = ReceiveBufferB[1]; //connect flags
  25. int maxpack = (0xff * ReceiveBufferB[2]) + ReceiveBufferB[3]; //max packet size
  26. return true;
  27. }
  28. else
  29. {
  30. return false;
  31. }
  32. }

4、发送文本内容

  1. //send client request, start put
  2. string tName = "BRT优惠卷.txt";
  3. string tType = "";
  4. string tFileContent = "优惠卷内容:" + this.txtContent.Text.Trim();
  5. int result = OBEXRequest("PUT", tName, tType, tFileContent);
  6. if (result == 160)
  7. {
  8. SendSuccess = true;
  9. }

完整代码

  1. using System;
  2. using System.Data;
  3. using System.Configuration;
  4. using System.Web;
  5. using System.Web.Security;
  6. using System.Web.UI;
  7. using System.Web.UI.WebControls;
  8. using System.Web.UI.WebControls.WebParts;
  9. using System.Web.UI.HtmlControls;
  10. using System.Net.Sockets;
  11. using OpenNETCF;
  12. using OpenNETCF.Net;
  13. using OpenNETCF.Net.Bluetooth;
  14. using OpenNETCF.Net.Sockets;
  15. public partial class _Default : System.Web.UI.Page
  16. {
  17. //Stream stream;
  18. NetworkStream stream;
  19. OpenNETCF.Net.Sockets.BluetoothClient client;
  20. protected void Page_Load(object sender, EventArgs e)
  21. {
  22. }
  23. #region ShowErrMsg
  24. private void ShowErrMsg(string err)
  25. {
  26. string str;
  27. str = "<script language='javascript'>";
  28. str += " alert('" + err + "')";
  29. str += "</script>";
  30. this.RegisterStartupScript("", str);
  31. }
  32. #endregion
  33. protected void btnSend_Click(object sender, EventArgs e)
  34. {
  35. if (this.txtContent.Text.Trim() == string.Empty)
  36. {
  37. this.ShowErrMsg("请输入发送内容!");
  38. return;
  39. }
  40. BluetoothClient bc = new BluetoothClient();
  41. BluetoothDeviceInfo[] bdi;
  42. bdi = bc.DiscoverDevices(10);//查找周围最多10个蓝牙设备
  43. if (bdi.Length == 0)
  44. {
  45. this.ShowErrMsg("请确认您的蓝牙已开启!");
  46. return;
  47. }
  48. bool SendSuccess = false;
  49. try
  50. {
  51. foreach (BluetoothDeviceInfo bd in bdi)
  52. {
  53. if (OBEXOpenStream(bd.DeviceID.ToString()))
  54. {
  55. if (OBEXConnect())
  56. {
  57. //send client request, start put
  58. string tName = "BRT优惠卷.txt";
  59. string tType = "";
  60. string tFileContent = "优惠卷内容:" + this.txtContent.Text.Trim();
  61. int result = OBEXRequest("PUT", tName, tType, tFileContent);
  62. if (result == 160)
  63. {
  64. SendSuccess = true;
  65. }
  66. }
  67. OBEXCloseStream();
  68. }
  69. else
  70. {
  71. this.ShowErrMsg("连接失败!" + bd.DeviceName.ToString());
  72. }
  73. }
  74. if (SendSuccess)
  75. {
  76. this.ShowErrMsg("发送成功,谢谢使用!");
  77. }
  78. }
  79. finally
  80. {
  81. OBEXCloseStream();
  82. }
  83. }
  84. #region OBEXOpenStream
  85. public bool OBEXOpenStream(string BTMAC)
  86. {
  87. // serial port UUID
  88. Guid spguid = OpenNETCF.Net.Bluetooth.BluetoothService.ObexObjectPush;
  89. OpenNETCF.Net.BluetoothAddress btaddress = OpenNETCF.Net.BluetoothAddress.Parse(BTMAC);
  90. client = new OpenNETCF.Net.Sockets.BluetoothClient();
  91. // define endpoint
  92. OpenNETCF.Net.BluetoothEndPoint endpoint = new OpenNETCF.Net.BluetoothEndPoint(btaddress, spguid);
  93. try
  94. {
  95. //open socket
  96. client.Connect(endpoint);
  97. }
  98. catch
  99. {
  100. //unable to connect (server not listening on spguid)
  101. return false;
  102. }
  103. //connect socket
  104. stream = client.GetStream();
  105. return true;
  106. }
  107. #endregion
  108. #region OBEXCloseStream
  109. private void OBEXCloseStream()
  110. {
  111. if (stream != null)
  112. {
  113. stream.Close();
  114. }
  115. if (client != null)
  116. {
  117. client.Close();
  118. }
  119. }
  120. #endregion
  121. #region OBEXConnect
  122. private bool OBEXConnect()
  123. {
  124. //send client request
  125. byte[] ConnectPacket = new byte[7];
  126. ConnectPacket[0] = 0x80; // Connect
  127. ConnectPacket[1] = 0x00; // Packetlength Hi Byte
  128. ConnectPacket[2] = 0x07; // Packetlength Lo Byte
  129. ConnectPacket[3] = 0x10; // Obex v1
  130. ConnectPacket[4] = 0x00; // no flags
  131. ConnectPacket[5] = 0x20; // 8k max packet size Hi Byte
  132. ConnectPacket[6] = 0x00; // 8k max packet size Lo Byte
  133. stream.Write(ConnectPacket, 0, ConnectPacket.Length);
  134. //listen for server response
  135. byte[] ReceiveBufferA = new byte[3];
  136. stream.Read(ReceiveBufferA, 0, 3);
  137. if (ReceiveBufferA[0] == 160) // 0xa0
  138. {
  139. //success, decode rest of packet
  140. int plength = (0xff * ReceiveBufferA[1]) + ReceiveBufferA[2]; //length of packet is...
  141. //listen for rest of packet
  142. byte[] ReceiveBufferB = new byte[plength - 3];
  143. stream.Read(ReceiveBufferB, 0, plength - 3);
  144. int obver = ReceiveBufferB[0]; //server obex version (16 = v1.0)
  145. int cflags = ReceiveBufferB[1]; //connect flags
  146. int maxpack = (0xff * ReceiveBufferB[2]) + ReceiveBufferB[3]; //max packet size
  147. return true;
  148. }
  149. else
  150. {
  151. return false;
  152. }
  153. }
  154. #endregion
  155. #region OBEXRequest
  156. private int OBEXRequest(string tReqType, string tName, string tType, string tFileContent)
  157. {
  158. //send client request
  159. int i;
  160. int offset;
  161. int packetsize;
  162. byte reqtype = 0x82;
  163. int tTypeLen = 0x03;
  164. int typeheadsize;
  165. int typesizeHi = 0x00;
  166. int typesizeLo = 0x03;
  167. //tName = "contact.vcf";
  168. //tType = "text/x-vCard";
  169. //tFileContent = "BEGIN:VCARD\r\nVERSION:2.1\r\nN:;aardvark\r\nFN:aardvark\r\nEND:VCARD\r\n";
  170. if (tReqType == "GET")
  171. {
  172. reqtype = 0x83; // 131 GET-Final
  173. }
  174. if (tReqType == "PUT")
  175. {
  176. reqtype = 0x82; // 130 PUT-Final
  177. }
  178. packetsize = 3;
  179. //Name Header
  180. int tNameLength = tName.Length;
  181. int nameheadsize = (3 + (tNameLength * 2) + 2);
  182. int namesizeHi = (nameheadsize & 0xff00) / 0xff;
  183. int namesizeLo = nameheadsize & 0x00ff;
  184. packetsize = packetsize + nameheadsize;
  185. if (tType != "")
  186. {
  187. //Type Header
  188. tTypeLen = tType.Length;
  189. typeheadsize = 3 + tTypeLen + 1;
  190. typesizeHi = (typeheadsize & 0xff00) / 0xff;
  191. typesizeLo = typeheadsize & 0x00ff;
  192. packetsize = packetsize + typeheadsize;
  193. }
  194. //Body
  195. int fileLen = System.Text.Encoding.Default.GetBytes(tFileContent).Length;//tFileContent.Length;
  196. int fileheadsize = 3 + fileLen;
  197. int filesizeHi = (fileheadsize & 0xff00) / 0xff; ;
  198. int filesizeLo = fileheadsize & 0x00ff; ;
  199. packetsize = packetsize + fileheadsize;
  200. int packetsizeHi = (packetsize & 0xff00) / 0xff;
  201. int packetsizeLo = packetsize & 0x00ff;
  202. byte[] tSendByte = new byte[packetsize];
  203. //PUT-final Header
  204. tSendByte[0] = reqtype; // Request type e.g. PUT-final 130
  205. tSendByte[1] = Convert.ToByte(packetsizeHi); // Packetlength Hi
  206. tSendByte[2] = Convert.ToByte(packetsizeLo); // Packetlength Lo
  207. offset = 2;
  208. //Name Header
  209. tSendByte[offset + 1] = 0x01; // HI for Name header
  210. tSendByte[offset + 2] = Convert.ToByte(namesizeHi); // Length of Name header (2 bytes per char)
  211. tSendByte[offset + 3] = Convert.ToByte(namesizeLo); // Length of Name header (2 bytes per char)
  212. // Name+\n\n in unicode
  213. byte[] tNameU = System.Text.Encoding.BigEndianUnicode.GetBytes(tName);
  214. tNameU.CopyTo(tSendByte, offset + 4);
  215. offset = offset + 3 + (tNameLength * 2);
  216. tSendByte[offset + 1] = 0x00; // null term
  217. tSendByte[offset + 2] = 0x00; // null term
  218. offset = offset + 2;
  219. if (tType != "")
  220. {
  221. //Type Header
  222. tSendByte[offset + 1] = 0x42; // HI for Type Header 66
  223. tSendByte[offset + 2] = Convert.ToByte(typesizeHi); // Length of Type Header
  224. tSendByte[offset + 3] = Convert.ToByte(typesizeLo); // Length of Type Header
  225. for (i = 0; i <= (tTypeLen - 1); i++)
  226. {
  227. tSendByte[offset + 4 + i] = Convert.ToByte(Convert.ToChar(tType.Substring(i, 1)));
  228. }
  229. tSendByte[offset + 3 + tTypeLen + 1] = 0x00; // null terminator
  230. offset = offset + 3 + tTypeLen + 1;
  231. }
  232. //Body
  233. tSendByte[offset + 1] = 0x49; //HI End of Body 73
  234. tSendByte[offset + 2] = Convert.ToByte(filesizeHi); //
  235. tSendByte[offset + 3] = Convert.ToByte(filesizeLo); //1k payload + 3 for HI header
  236. //for (i = 0; i <= (fileLen - 1); i++)
  237. //{
  238. // tSendByte[offset + 4 + i] = Convert.ToByte(tFileContent.Substring(i, 1));//Convert.ToByte(Convert.ToChar(tFileContent.Substring(i, 1)));
  239. //}
  240. byte[] bfile = System.Text.Encoding.Default.GetBytes(tFileContent);
  241. for (i = 0; i <= bfile.Length - 1; i++)
  242. {
  243. tSendByte[offset + 4 + i] = bfile[i];
  244. }
  245. //tSendByte[offset+4+fileLen] = 0x00; // null terminator
  246. offset = offset + 3 + fileLen;
  247. stream.Write(tSendByte, 0, tSendByte.Length);
  248. //listen for server response
  249. //TODO: can hang here forever waiting response...
  250. bool x = stream.DataAvailable; // changed bluetoothclient - public NetworkStream GetStream()
  251. byte[] tArray4 = new byte[3];
  252. stream.Read(tArray4, 0, 3);
  253. x = stream.DataAvailable;
  254. if (tArray4[0] == 160) // 0xa0
  255. {
  256. int plength = (tArray4[1] * 256) + tArray4[2] - 3;
  257. byte[] tArray5 = new byte[plength];
  258. if (plength > 0)
  259. {
  260. stream.Read(tArray5, 0, plength);
  261. //TODO: data in returned packet to deal with
  262. }
  263. return 160;
  264. }
  265. if (tArray4[0] == 197) // 0xc5 Method not allowed
  266. {
  267. return 197;
  268. }
  269. if (tArray4[0] == 192) // 0xc0 Bad Request
  270. {
  271. return 192;
  272. }
  273. return 0;
  274. }
  275. #endregion
  276. }

参考资料