You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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);
    }
}

关键修复点

  1. 解决数据错误/慢的问题:ObexListener自动解析OBEX协议,Request.InputStream直接提供纯文件内容;CopyTo方法内部优化了缓冲区和读写逻辑,比手动循环更高效。
  2. 获取文件扩展名:通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:58:28