请教熟悉用32feet开发蓝牙程序的朋友

comiunknown 2009-10-28 11:13:04
我用32feet,按照32feet的例子,写了一个电脑(电脑上使用的是usb蓝牙棒)到手机之间通过蓝牙互传文件的测试程序。但是发现互传文件经常失败。主要问题有3个:
1、如果文件名是中文的话,失败的几率非常大。而且一旦发送失败后,后面再继续发文件,仍旧失败。除非把电脑上的蓝牙棒拔下来,重新插,再重新启动程序才能恢复正常。貌似失败后蓝牙传输通道被堵塞,导致后面的数据无法正常传送。请问有没有办法通过编程代码来重新疏通蓝牙通道?
2、调试电脑端接收手机传过来的蓝牙文件时,在下面这句
olr.WriteFile(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal) + "\\" + DateTime.Now.ToString("yyMMddHHmmss") + " " + filename);
放断点,这里能正确获取到手机传过来的文件名,但是WriteFile后在电脑上没发现生成文件,32feet的帮助文档上,ObexListenerRequest.WriteFile()的帮助信息太少了,请问有没有办法得到写文件失败的具体原因?
3、用obexwebresponse获取回执的时间太长,我传一个10kb不到的文件,等这个回执经常等20秒左右,而且还经常超时报错,但是手机上还是正确收到了传过来的这个文件。我用XP自带的蓝牙配置程序传输文件时感觉比我自己用32feet写的程序快一些,稳定性也高一些,请问有办法提高32feet蓝牙传输效率和稳定性吗?
...全文
335 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
kay_ 2009-11-13
  • 打赏
  • 举报
回复
OK。嗯 - -单位断了良久的网。。好的。我去看看你的例子。
comiunknown 2009-11-02
  • 打赏
  • 举报
回复
to yuwushen:
你的代码我调试过了,稳定性的确比32feet.net的ObexWebRequest,ObexWebResponse强,另外查资料发现32feet.net的论坛上有人推荐用Brecham.Obex库来做文件收发,至少大文件传输用它不会出错。可能这个更稳定点,我这几天改成它试试,这贴先结了。

另外推荐一篇不错的Obex传输例子:
http://www.codeproject.com/KB/mobile/ObeXplorer.aspx
comiunknown 2009-10-31
  • 打赏
  • 举报
回复
收到,你的程序调试有点问题,连接设备是写死的,我下周改了仔细测一下。我这边用32feet.net写的PC端蓝牙收发程序比你的灵活一些,比较方便调试。
kay_ 2009-10-30
  • 打赏
  • 举报
回复
发过去了。注意查收
comiunknown 2009-10-29
  • 打赏
  • 举报
回复
我的邮箱:bobcy@21cn.com,谢了。
kay_ 2009-10-29
  • 打赏
  • 举报
回复
中文的以前试过一个2M多的文件传输没问题。还传过一个40多M的音频文件,也没问题。哦。。原来他自带着收发文件的方法啊。。- -。。。你留个邮箱,我把我代码给你发过去你试试
comiunknown 2009-10-28
  • 打赏
  • 举报
回复
用32feet.net的ObexWebRequest,ObexWebResponse传文件,只要文件名中不含中文,基本上都能成功,我测试传成功最大的文件大小是1.6MB,但是中文名的文件传失败的几率比较大。

还有,手机我这里用2个平台的都测过,WM手机蓝牙收发我电脑上蓝牙程序的文件成功率比较高,nokia s60的成功率相对较低,但是在查找蓝牙设备时,nokia手机的发现速度比WM手机快,每次都是第一个找到nokia手机的蓝牙。
comiunknown 2009-10-28
  • 打赏
  • 举报
回复
to yuwushen:
对,我用的就是InTheHand.Net.Personal,看他的介绍
32feet.NET is a shared-source project to make personal area networking technologies such as Bluetooth, Infrared (IrDA) and more, easily accessible from .NET code. It supports desktop, mobile or embedded systems. The project currently consists of the following technologies
貌似是免费开源的。用它开发bluetooth的应用程序比较方便,他的ObexWebRequest,ObexWebResponse就是把你代码里面的数据包读写封装好了直接用,它的代码很简单,发文件就这样几句:
System.Uri uri = new Uri("obex://" + sbdd.SelectedDevice.DeviceAddress.ToString() + "/" + System.IO.Path.GetFileName(ofdFileToBeam.FileName));
ObexWebRequest request = new ObexWebRequest(uri);
request.ReadFile(ofdFileToBeam.FileName);
ObexWebResponse response = (ObexWebResponse)request.GetResponse();
MessageBox.Show(response.StatusCode.ToString());
response.Close();
问题是数据包发出去后,对方设备接没接收到没反应,而且经常超时卡住,帮助文档感觉就是机器自动生成的,一点有助于出错调试的提示都找不到。

另外,你的代码测试发大一点的中文名的文件成功过没?
kay_ 2009-10-28
  • 打赏
  • 举报
回复
还有问楼主个问题

我用的是InTheHand.Net.Personal

inthehand本身貌似是收费的。这个东西会不会用的一段时间失效啥的
kay_ 2009-10-28
  • 打赏
  • 举报
回复
这是手机端

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using InTheHand.Net.Sockets;
using InTheHand.Net.Bluetooth;
using System.IO;
using System.Threading;

namespace sdsd
{
public class BlueTooth
{

private BluetoothListener bl;
private Guid service = BluetoothService.SerialPort;
private bool listening = true;
private static readonly int _blockLength = 500 * 1024;

public BlueTooth()
{

bl = new BluetoothListener(service);
bl.Start();

Thread t = new Thread(new System.Threading.ThreadStart(ListenLoop));
t.Start();



}

private void ListenLoop()
{
while (true)
{
while (listening)
{
BluetoothClient bc;
System.IO.Stream s;
try
{
bc = bl.AcceptBluetoothClient();

s = bc.GetStream();

}
catch (Exception ex)
{
MessageBox.Show("" + ex);
break;
}

//keep connection open

while (listening)
{

string filename = GetAddress("cmd.txt");

string path = filename;
try
{

if (ReceiveFile(path, s))
{


}
else
{
break;
}
}
catch
{
break;
}

}

try
{
long count = GetSize(s);
if (count == 0)
{
s.Flush();
s.Close();
bc.Close();
}

}
catch
{
// break;
}

}

}

}

/// <summary>
/// 接收文件
/// </summary>
/// <param name="filePath"></param>
/// <param name="stream"></param>
/// <returns></returns>
internal bool ReceiveFile(string filePath, Stream stream)
{
try
{
long count = GetSize(stream);
if (count == 0)
{
return false;
}

long index = 0;
byte[] clientData = new byte[_blockLength];
if (File.Exists(filePath))
{
File.Delete(filePath);
}
string path = new FileInfo(filePath).Directory.FullName;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}

FileStream fs = File.Open(filePath, FileMode.OpenOrCreate);
try
{
//计算当前要读取的块的大小
int currentBlockLength = 0;
if (_blockLength < count - index)
{
currentBlockLength = _blockLength;
}
else
{
currentBlockLength = (int)(count - index);
}

int receivedBytesLen = stream.Read(clientData, 0, currentBlockLength);
index += receivedBytesLen;
fs.Write(clientData, 0, receivedBytesLen);

while (receivedBytesLen > 0 && index < count)
{
clientData = new byte[_blockLength];
receivedBytesLen = 0;

if (_blockLength < count - index)
{
currentBlockLength = _blockLength;
}
else
{
currentBlockLength = (int)(count - index);
}
receivedBytesLen = stream.Read(clientData, 0, currentBlockLength);
index += receivedBytesLen;
fs.Write(clientData, 0, receivedBytesLen);
}
}
catch (Exception ex)
{
MessageBox.Show("" + ex);
return false;
}
finally
{
fs.Close();
}
}
catch (Exception ex)
{
MessageBox.Show("" + ex);
return false;
}
return true;
}

/**/
/// <summary>
/// 获取要读取的数据的大小
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
private int GetSize(Stream stream)
{
int count = 0;
byte[] countBytes = new byte[8];
try
{
if (stream.Read(countBytes, 0, 8) == 8)
{
count = BitConverter.ToInt32(countBytes, 0);
}
else
{
return 0;
}
}
catch (Exception ex)
{
MessageBox.Show("" + ex);
}
return count;
}



private String GetAddress(String str)
{
String fileName = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
fileName = Path.GetDirectoryName(fileName);
return Path.Combine(fileName, str);

}
/// <summary>
/// 停止监听
/// </summary>
private void StopBt()
{

listening = false;
bl.Stop();

}

}
}
kay_ 2009-10-28
  • 打赏
  • 举报
回复
个人感觉是lz的数据包收发问题。以前用32feet做过一简单的数据收发功能(pc传文件到蓝牙)。也出现过lz的问题。最后是改用了别人的数据包格式(之前自己是把头100字节当数据头 文件名|文件大小|文件数据。。。写的那叫一个垃圾)不是用的obex
这是pc端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using InTheHand.Net;
using InTheHand.Net.Sockets;
using InTheHand.Net.Bluetooth;
using System.IO;
using System.Threading;
namespace WindowsApplication8
{
public partial class Form1 : Form
{
/// <summary>
/// 蓝牙客户端实例,每个实例对应一个手机蓝牙
/// </summary>
private BluetoothClient bc;
private BluetoothClient bc2;
/// <summary>
/// 蓝牙连接服务的guid,两端要一致才能建立连接
/// </summary>
private Guid service = BluetoothService.SerialPort;


public Form1()
{
InitializeComponent();

}



private void Form1_Load(object sender, System.EventArgs e)
{

//蓝牙广播方式 可见,可连接,关闭
//一些设备中这段代码无效,建议保留
BluetoothRadio radio = BluetoothRadio.PrimaryRadio;
if (radio != null && radio.Mode == RadioMode.PowerOff)
{
BluetoothRadio.PrimaryRadio.Mode = RadioMode.Connectable;
}
//蓝牙客户端实例化
bc = new BluetoothClient();
bc2 = new BluetoothClient();
this.label1.Text = "点击连接进行设备连接";
//发送键初始设置为不可操作
this.send.Enabled = false;
//发送2键初始设置为不可操作
this.button1.Enabled = false;
}
/// <summary>
/// 查找蓝牙设备,搜索周围可见蓝牙设备
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void search_Click(object sender, EventArgs e)
{
try
{
//this will take a while...


//鼠标游标转为等待状态
Cursor.Current = Cursors.WaitCursor;
//查找可见设备
BluetoothDeviceInfo[] bdi = bc.DiscoverDevices(12);

//cmbdevice中显示设备列表
cmbDevices.DataSource = bdi;
//将123去掉显示蓝牙设备名,否则是蓝牙地址
cmbDevices.DisplayMember = "123DeviceName";

cmbDevices.ValueMember = "DeviceAddress";
//设置蓝牙列表可见,目前是不可见状态,保留到需要显示蓝牙地址时使用

// cmbDevices.Visible = true;

cmbDevices.Focus();

//游标设为默认状态
Cursor.Current = Cursors.Default;


//如果搜索到设备,进行连接操作
if (bdi.Length > 0)
{
link.Enabled = true;
// link.Visible = true;
link_Click(null, null);

}
}
catch
{

}

}
/// <summary>
/// 建立蓝牙连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void link_Click(object sender, EventArgs e)
{
if (cmbDevices.SelectedValue != null)
{
try
{ //蓝牙设备地址
string ac = "00178331D688";
string ac1 = "080028DAF37C";
//将字符串转为蓝牙地址实例
BluetoothAddress add1 = BluetoothAddress.Parse(ac);
BluetoothAddress add2 = BluetoothAddress.Parse(ac1);
//使用蓝牙地址和guid建立endpoint
BluetoothEndPoint btep = new BluetoothEndPoint(add1, service);
try
{
//与蓝牙设备连接,使bc与设备对应。注意发送接收数据的目标是用bc来确定的
bc.Connect(btep);
// this.send.BackColor = Color.PaleGreen;
//发送键设置为可操作
this.send.Enabled = true;
}
catch(Exception ex)
{
MessageBox.Show(ex + "");
// this.send.BackColor = Color.Salmon;
}

BluetoothEndPoint btep2 = new BluetoothEndPoint(add2, service);

try
{
bc2.Connect(btep2);
this.button1.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex + "");

}
link.Enabled = false;
this.Controls.Remove(cmbDevices);
this.BackColor = Color.PaleGreen;
this.Focus();
this.label1.Text = "连接成功";

this.search.Enabled = false;

}
catch (Exception ex)
{
MessageBox.Show(ex + "");
//MessageBox.Show("请确认设备已开启");
this.BackColor = Color.Salmon;
}
}
}

/// <summary>
/// 关闭蓝牙连接并关闭程序窗口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void close_Click(object sender, EventArgs e)
{

bc.Close();
this.Close();


}

private void send_Click(object sender, EventArgs e)
{

sendFile(@"c:\cmd.txt", bc);

}
/// <summary>
/// 获取程序运行时的路径
/// </summary>
/// <param name="str"></param>
/// <returns></returns>

private String GetAddress(String str)
{
String fileName = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
fileName = Path.GetDirectoryName(fileName);
return Path.Combine(fileName, str);

}
/// <summary>
/// 向目标蓝牙发送数据
/// </summary>
/// <param name="filename">文件名</param>
/// <param name="bc">发送数据的目标蓝牙实例</param>
private void sendFile(String filename, BluetoothClient bc)
{

try
{
//声明数据流为蓝牙数据流
System.IO.Stream s = bc.GetStream();

String path = null;

//获取程序运行地址,这里文件名指定为cmd.txt 方法的filename参数没有使用
path = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
path = path + "\\cmd.txt";
SendFile(path, s);


}
catch (Exception ex)
{

MessageBox.Show(ex + "");
}


}


/// <summary>
/// 每次发送的数据块大小 5k
/// </summary>
private static readonly int _blockLength = 500 * 1024;

/// <summary>
/// 发送文件,此发送文件发法把数据流分为两部分,头8字节存储文件长度,剩下的部分为文件数据
/// </summary>
/// <param name="filePath">文件路径</param>
/// <param name="stream">文件写入的数据流</param>
/// <returns></returns>
internal bool SendFile(string filePath, Stream stream)
{
//打开文件
FileStream fs = File.Open(filePath, FileMode.Open);
//文件长度
int readLength = 0;
//设置字节缓冲区5k
byte[] data = new byte[_blockLength];

//文件大小字节缓冲
byte[] length = new byte[8];
//将文件大小写入到length中,再从length中取8个字节写入到stream中
BitConverter.GetBytes(new FileInfo(filePath).Length).CopyTo(length, 0);
stream.Write(length, 0, 8);

//发送文件 每次从fs中读取_blockLength大小的字节数据写入到stream中,直到fs中没有数据
//注意read用法,指针自动后移
while ((readLength = fs.Read(data, 0, _blockLength)) > 0)
{
stream.Write(data, 0, readLength);
}
MessageBox.Show("发送成功");


//关闭文件
fs.Close();
return true;
}
/// <summary>
/// 向第二个蓝牙设备发送文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
sendFile(@"c:\cmd.txt", bc2);

}


/*需要增加设备时,1、修改search_click中的内容显示蓝牙地址
* 2、声明一个新的客户端实例 如private BluetoothClient bc3 = new BluetoothClient ();
* 3、在link_click中增加蓝牙地址,设置endpoint 建立连接
* 4、添加发送button,调用sendFile方法参数2设置为bc3
*
* */





}
}
ProgrammerNO1 2009-10-28
  • 打赏
  • 举报
回复
32feet最先进技术?

7,655

社区成员

发帖
与我相关
我的任务
社区描述
Windows Phone是微软发布的一款手机操作系统,它将微软旗下的Xbox LIVE游戏、Zune音乐与独特的视频体验整合至手机中。
社区管理员
  • Windows客户端开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧