基于32feet.NET的C#蓝牙文件接收监听问题求助
问题解决方案(基于32feet.NET & 替代方案)
现有代码问题根源
你直接读取BluetoothClient的原始流,没有解析OBEX协议(ObexObjectPush服务基于该协议),导致写入的文件包含OBEX头部元数据(非纯文件内容),同时协议处理不当引发读取效率低下。另外,文件名(含扩展名)通过OBEX请求头部传递,需从协议中提取,而非直接忽略。
修复后的32feet.NET实现
改用ObexListener专门处理OBEX协议,自动解析请求头部并提取纯文件内容:
using InTheHand.Net; using InTheHand.Net.Bluetooth; using InTheHand.Net.Sockets; using System.IO; using System.Threading; public partial class Form1 : Form { private ObexListener _obexListener; private Thread _listenerThread; public Form1() { InitializeComponent(); // 初始化OBEX监听器,绑定ObexObjectPush服务 _obexListener = new ObexListener(BluetoothService.ObexObjectPush); _listenerThread = new Thread(ListenForObexRequests); _listenerThread.IsBackground = true; // 后台线程,窗体关闭时自动终止 _listenerThread.Start(); } private void ListenForObexRequests() { _obexListener.Start(); while (true) { try { ObexListenerContext context = _obexListener.GetContext(); if (context != null) { HandleIncomingObexFile(context); } } catch (IOException ex) { Console.WriteLine("异常: " + ex.Message); } } } private void HandleIncomingObexFile(ObexListenerContext context) { string savePath = @"C:\BluetoothReceivedFiles\"; if (!Directory.Exists(savePath)) { Directory.CreateDirectory(savePath); } // 从OBEX请求头部提取原始文件名(含扩展名) string fileName = context.Request.Headers.GetSingleHeader(ObexHeaderName.Name)?.ToString() ?? $"ReceivedFile_{DateTime.Now:yyyyMMddHHmmss}"; string fullPath = Path.Combine(savePath, fileName); // 高效复制纯文件内容(自动跳过OBEX协议头部) using (FileStream fileStream = File.Create(fullPath)) { context.Request.InputStream.CopyTo(fileStream); } // 发送成功响应,告知发送方传输完成 context.SendResponse(ObexResponseCode.Success); } }
关键修复点
- 解决数据错误/慢的问题:
ObexListener自动解析OBEX协议,Request.InputStream直接提供纯文件内容;CopyTo方法内部优化了缓冲区和读写逻辑,比手动循环更高效。 - 获取文件扩展名:通过
ObexHeaderName.Name头部提取发送方传递的原始文件名,自然包含扩展名;若发送方未提供文件名,用时间戳生成默认文件名避免冲突。
替代方案:Windows原生蓝牙API
如果32feet.NET的稳定性不符合需求,可调用Windows原生API实现,依赖系统自带的蓝牙文件传输逻辑,无需手动处理流和协议:
using System.Runtime.InteropServices; public partial class Form1 : Form { [StructLayout(LayoutKind.Sequential)] private struct BLUETOOTH_ADDRESS { public ulong ullLong; } [DllImport("bthprops.cpl", CharSet = CharSet.Unicode)] private static extern int BluetoothReceiveFile(IntPtr hwndOwner, ref BLUETOOTH_ADDRESS pbthAddress); // 调用示例(触发系统蓝牙文件接收对话框) private void btnReceiveFile_Click(object sender, EventArgs e) { BLUETOOTH_ADDRESS address = new BLUETOOTH_ADDRESS(); // 若需指定接收设备,可设置address.ullLong为设备蓝牙地址;留空则让系统选择设备 BluetoothReceiveFile(this.Handle, ref address); } }
该方案自定义程度低,但无需处理底层协议,适合快速实现基础文件接收功能。
内容的提问来源于stack exchange,提问作者TheMajidz
相关产品推荐
相关产品推荐

