当前位置: 首页 > 面试题库 >

Android BluetoothSocket-超时

鞠子轩
2023-03-14
问题内容

我已经编写了用于连接外部附件的蓝牙API。该API的设计方式是,有一帮阻塞调用如getTimesetTimegetVolumesetVolume,等方式,这些工作是他们创造一个有效载荷发送,并调用一个名为方法sendAndReceive(),做一些准备工作,并最终做的以下:

byte[] retVal = null;
BluetoothSocket socket = getSocket();
// write
socket.getOutputStream().write(payload);
// read response
if(responseExpected){
    byte[] buffer = new byte[1024]; // buffer store for the stream
    int readbytes = socket.getInputStream().read(buffer);
    retVal = new byte[readbytes];
    System.arraycopy(buffer, 0, retVal, 0, readbytes);
}
return retVal;

问题在于,有时此设备会变慢或无法响应,因此我想在此呼叫上设置超时。我尝试了几种方法将此代码放入thread \ future任务并使其超时运行,例如:

FutureTask<byte[]> theTask = null;
// create new task
theTask = new FutureTask<byte[]>(
        new Callable<byte[]>() {

            @Override
            public byte[] call() {
                byte[] retVal = null;
                BluetoothSocket socket = getSocket();
                // write
                socket.getOutputStream().write(payload);
                // read response
                if(responseExpected){
                    byte[] buffer = new byte[1024]; // buffer store for the stream
                    int readbytes = socket.getInputStream().read(buffer);
                    retVal = new byte[readbytes];
                    System.arraycopy(buffer, 0, retVal, 0, readbytes);
                }
                return retVal;
            }
        });

// start task in a new thread
new Thread(theTask).start();

// wait for the execution to finish, timeout after 6 secs
byte[] response;
try {
    response = theTask.get(6L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
    throw new CbtException(e);
} catch (ExecutionException e) {
    throw new CbtException(e);
} catch (TimeoutException e) {
    throw new CbtCallTimedOutException(e);
}
    return response;
}

这种方法的问题在于我无法在调用方法中重新抛出异常,并且由于某些方法抛出了异常,因此我想转发回API客户端,因此我无法使用此方法。

您可以推荐其他替代方法吗?谢谢!


问题答案:

为什么不尝试类似的东西

public class ReadTask extends Thread {
  private byte[] mResultBuffer;
  private Exception mCaught;
  private Thread mWatcher;
  public ReadTask(Thread watcher) {
    mWatcher = watcher;
  }

  public void run() {
    try {
      mResultBuffer = sendAndReceive();
    } catch (Exception e) {
      mCaught = e;
    }
    mWatcher.interrupt();
  }
  public Exception getCaughtException() {
    return mCaught;
  }
  public byte[] getResults() {
    return mResultBuffer;
  }
}

public byte[] wrappedSendAndReceive() {
  byte[] data = new byte[1024];
  ReadTask worker = new ReadTask(data, Thread.currentThread());

  try {
    worker.start();
    Thread.sleep(6000);
  } catch (InterruptedException e) {
    // either the read completed, or we were interrupted for another reason
    if (worker.getCaughtException() != null) {
      throw worker.getCaughtException();
    }
  }

  // try to interrupt the reader
  worker.interrupt();
  return worker.getResults;
}

这里有一个wrappedSendAndReceive()极端的情况,即线程调用可能由于某种原因而不是ReadTask的中断而被中断。我想可以在ReadTask中添加完成的位,以允许另一个线程测试读取是否完成或中断是由其他原因引起的,但是我不确定这样做的必要性。

还要注意的是,此代码确实包含数据丢失的可能性。如果6秒钟到期并且已读取了一些数据,则最终将被丢弃。如果要解决此问题,则需要一次在ReadTask.run()中读取一个字节,然后适当地捕获InterruptedException。显然,这需要对现有代码进行一些重做以保持计数器并在接收到中断时适当调整读取缓冲区的大小。



 类似资料:
  • 当我们所有数据库的 SQL 语句是通过子查询方式完成,对于超时的控制往往很容易被大家忽略。因为大家在代码里看不到任何调用 set_timeout 的地方。实际上 PostgreSQL 已经为我们预留好了两个设置。 请参考下面这段配置: location /postgres { internal; default_type text/html; set_by_lua_blo

  • 你是否正遇到网络或 CPU 的瓶颈? 验证客户端和托管redis-server的服务器上支持的最大带宽。如果有请求被带宽限制,则它们需要更长时间才能完成,从而可能导致超时。 同样,验证您没有在客户端或服务器框上获得CPU限制,这将导致请求等待CPU时间,从而超时。 有没有命令需要在 redis 服务器上处理很长时间? 可能有一些命令需要很长时间才能在redis服务器上处理,导致请求超时。 长时间

  • 套房级 套件级超时可应用于整个测试“套件”,或通过其禁用this.timeout(0)。这将由所有嵌套套件和不覆盖该值的测试用例继承。 describe('a suite of tests', function() { this.timeout(500); it('should take less than 500ms', function(done){ setTimeout(done, 30

  • 我使用命令生成器在Jenkins服务器上运行单元测试。phar exec“codecept运行单元应用程序/模型”-vvv并获取以下错误: [Symfony\Component\Process\Exception\ProcessTimedOutException] 进程“codecept运行单元应用程序/模型”超过了1800秒的超时时间。 我如何修复它并允许测试花费更多的时间?谢谢

  • 你知道是怎么回事吗?

  • 问题内容: 我正在使用SwingWorker通过TCP连接读取数据并在数据返回时显示。 当套接字失效时,例如在writeTo之后,它将永久等待套接字上的输入,从而产生问题。一段时间后最简单的超时方法是什么?是否这也是在这种情况下,最好的解决办法?在该解决方案中,我还会使用摇摆工人吗? 谢谢 问题答案: 是的,您链接到的解决方案是一个合理且简单的解决方案(“ best”太主观了:)您可以利用Swin

  • 示例: timeout 超时机制可以保护服务调用陷入无限的等待之中。超时定义了服务的最长等待时间,如果在给定的时间没有相应,服务调用就进入下一个状态,或者重试、或者立即返回错误。 Server 你可以使用OptionFn设置服务器的 readTimeout 和 writeTimeout。 ```go server struct type Server struct { …… readTimeout

  • 超时对那些连接外部资源的程序来说是很重要的,否则就需要限定执行时间。在Go里面实现超时很简单。我们可以使用channel和select很容易地做到。 package main import "time" import "fmt" func main() { // 在这个例子中,假设我们执行了一个外部调用,2秒之后将结果写入c1 c1 := make(chan string, 1)