【问题标题】:How to ensure all data is sent before closing Android BluetoothSocket如何确保在关闭 Android BluetoothSocket 之前发送所有数据
【发布时间】:2017-06-08 16:19:37
【问题描述】:

我正在制作一个安卓应用程序,它将通过蓝牙在手机之间进行通信。为了节省电池,我想避免一直保持蓝牙连接打开。所以每次我要发送消息时,我都会打开一个连接,发送消息,刷新,然后关闭。

我的问题是有时,但并非总是如此,接收电话会给我臭名昭著的“java.io.IOException: bt socket closed, read return: -1”。我看到BluetoothSocket documentation 状态

BluetoothSocket 是线程安全的。特别是,close() 总是会立即中止正在进行的操作并关闭套接字。

但是,一般Bluetooth page 表示:

当您使用完 BluetoothSocket 后,请始终调用 close()。这样做会立即关闭连接的套接字并释放所有相关的内部资源。

这是我发送消息的线程的摘录。

            localSocket = device.createRfcommSocketToServiceRecord(MY_UUIDS[0]);
            localSocket.connect();
            Log.d(TAG, "Correctly Connected on " + MY_UUIDS[0]);
            OutputStream rawOutputStream = localSocket.getOutputStream();
            ObjectOutputStream messageOutputStream = new ObjectOutputStream(rawOutputStream);
            // Actually send the message
            messageOutputStream.writeObject(message);
            messageOutputStream.flush();
            rawOutputStream.flush();

            messageOutputStream.close();
            rawOutputStream.close();
            localSocket.close();

这是我接受传入连接的线程的摘录:

                    InputStream rawInputStream = socket.getInputStream();
                    ObjectInputStream messageInputStream = new ObjectInputStream(rawInputStream);
                    BluetoothMessage joinMessage = (BluetoothMessage) messageInputStream.readObject();
                    BluetoothDevice device = socket.getRemoteDevice();
                    messageInputStream.close();
                    rawInputStream.close();
                    socket.close();
                    socket = null;

我意识到刷新和关闭是多余的,但事实是 有时 由于硬件延迟,套接字在发送所有消息之前在发送端关闭。

我可以确认所有消息每次都完美到达,无论我发送它们的速度有多快......如果我不关闭套接字。但是,我知道关闭套接字始终是最佳做法。

那么我如何确保在调用 socket.close() 之前发送所有消息? 显然,flush() 和流 close() 没有做他们做的事情应该是,否则,无论我何时调用 socket.close(),消息都会被完全发送。

【问题讨论】:

  • 你不需要任何刷新,你只需要关闭对象输出流。很难相信close() 会中止,即中止正在进行的所有传输。在实践中真的是这样吗?

标签: java android bluetooth android-bluetooth bluetooth-socket


【解决方案1】:

首先,我想说你的第一个假设并不完全正确。如果这两个设备要不断地进行通信,那么实际上保持连接打开可能会更有效。

但是关于您的问题,确实有时在抛出 IOException 时传入的字节可能没有被完全读取。

确保实现的唯一方法是实现某种协议,您可以:

  1. 从一台设备写入数据
  2. 从远程设备读取它
  3. 从远程设备回复某种“ack”以确认您的数据已被完全读取。
  4. 只有在收到“ack”后才关闭套接字。

【讨论】:

  • 是的,这实际上是我最终做的。在应用程序中,我可能有多达七台设备与服务器设备进行通信,因此出于电池原因,我排除了保持连接打开的可能性。我担心 ack 方法不起作用,因为远程设备在发送 ack 后需要关闭套接字,这可能会导致与原始消息发送相同的问题。因此,为了解决这个问题,我让远程设备调用 read() 返回负值,直到发生异常以知道第一个设备何时关闭其套接字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-08
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多