【问题标题】:Problem with Sending and Receiving Files with SPP over Bluetooth通过蓝牙使用 SPP 发送和接收文件的问题
【发布时间】:2010-12-08 04:04:29
【问题描述】:

我正在尝试通过蓝牙使用 SPP(在 Java 中,使用 BlueCove API)在两台 PC 之间传输文件(大小约为 6 MB 的 MP3)。我可以使文件传输在一个方向上正常工作(例如,一个文件从客户端到服务器),但是当我尝试在同一会话期间向相反方向发送任何数据时(即从服务器发送一个文件到客户端),程序冻结,不会前进。

例如,如果我只是:

StreamConnection conn;
OutputStream outputStream;

outputStream = conn.openOutputStream();

....

outputStream.write(data);  //Data here is an MP3 file converted to byte array

outputStream.flush();

传输工作正常。但如果我尝试:

StreamConnection conn;
OutputStream outputStream;
InputStream inputStream;
ByteArrayOutputStream out = new ByteArrayOutputStream();

outputStream = conn.openOutputStream();
inputStream = conn.openInputStream();

....

outputStream.write(data);
outputStream.flush();


int receiveData;
while ((receiveData = inputStream.read()) != -1) {
   out.write(receiveData);
}

客户端和服务器都冻结,不会前进。我可以看到文件传输实际上是在某个时候发生的,因为如果我终止客户端,服务器仍会将文件写入硬盘驱动器,没有任何问题。我可以尝试用另一个文件来响应,或者只用一个整数来响应,但它仍然不起作用。

有人知道问题是什么吗?我知道 OBEX 通常用于通过蓝牙传输文件,但对于我需要做的事情来说似乎有点过分了。我必须使用 OBEX 来实现此功能吗?

【问题讨论】:

  • 可以发一份客户端代码的总结吗?
  • Wire dumps(使用某种嗅探器)肯定会有所帮助。您可能想使用 Wireshark 之类的东西来转储它并附加到这个问题

标签: java file-upload bluetooth


【解决方案1】:

这可能很简单,就像两个程序都卡在阻塞接收呼叫中,等待另一端说些什么...尝试添加大量日志语句,以便您可以看到每个程序处于什么“状态”(即,因此它会为您提供运行中的评论,例如“尝试接收”、“获取 xxx 数据”、“尝试回复”等),或设置调试,等到卡住然后停止其中一个并单步执行.

【讨论】:

  • 看来这两个程序都在阻止接收呼叫。写入操作是非阻塞的,写入输出流不会返回任何内容以指示传输已完成。无论如何,我还没有发现一直等到传输完成才开始监听连接(除了在 for 循环中一次写入一个字节,或者其他可能需要永远的变化)。一旦你调用 inputStream.read(),输出显然被中断了。
  • 如果您不知道如何将其置于非阻塞模式或查询数据可用性(文档对 InputStream.available() 的可靠性不太感兴趣,但它可能会更好而不是盲目地发出读取),你能通过从不同的线程读取来解决这个问题吗?
【解决方案2】:

您当然可以使用 SPP 在您的应用程序之间传输文件(假设您使用您的应用程序在两端发送和接收)。从代码 sn-p 很难判断你的程序出了什么问题。 我猜您将不得不关闭流,以向另一方表明您已完成发送数据。请注意,即使您将整个文件写入一个块,SPP / 蓝牙协议层可能会将其分段,并且另一端可以分片接收,所以你需要有一些协议来指示传输完成。

【讨论】:

    【解决方案3】:

    不看客户端代码很难说,但我猜,如果两者运行相同的代码(即都先写,然后读),是outputStream需要先关闭读取发生(否则,双方都将等待对方关闭自己的一侧以退出读取循环,因为read() 仅在另一侧关闭时返回-1)。

    如果不应该关闭流,那么停止读取的条件不能是等待-1。 (因此,要么将其更改为首先传输文件大小,要么采用其他机制)。

    【讨论】:

      【解决方案4】:

      您为什么决定使用 ByteArrayOutputStream?试试下面的代码:

          try {
              try {
      
                  byte[] buf = new byte[1024];
      
                  outputstream = conn.openOutputStream();
                  inputStream = conn.openInputStream();
      
                  while ((n = inputstream.read(buf, 0, 1024)) > -1)
                      outputstream.write(buf, 0, n);                
      
              } finally {
                  outputstream.close();
                  inputstream.close();
                  log.debug("Closed input streams!");
              }
          } catch (Exception e) {
          log.error(e);
              e.printStackTrace();
          }
      

      要转换 outputStream,您可以执行以下操作:

      byte currentMP3Bytes[] = outputStream.toString().getBytes();
      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(currentMP3Bytes);
      

      【讨论】:

      • 使用了ByteArrayOutputStream,因为我事先并不知道要通过网络传输的文件的大小。鉴于文件是歌曲并且可能非常大(想想 20 分钟长的管弦乐乐谱)或相对较小,分配一个通用大小的缓冲区似乎不切实际。根据我所做的研究,这显然是一种相当普遍的做法。
      猜你喜欢
      • 2015-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-13
      • 1970-01-01
      • 2013-08-02
      • 1970-01-01
      相关资源
      最近更新 更多