Android2.2 Socket关闭Bug的解决方…

    Android2.2有一个Bug:调用Socket close方法后,阻塞在Socket读上的线程不会抛出IOException,而是继续阻塞(http://code.google.com/p/android/issues/detail?id=7933)。这对于非echo类的TCP应用来说可能是致命的。因为一种通常做法是socket连接后,建立一个线程专门来接收数据。socket关闭,接收线程阻塞读要么扔异常,要么返回错误。但这个Bug导致本地接收线程继续阻塞,还可能导致此Socket无法释放,remote端仍以为连接可用。
    有个办法能轻松解决这个bug,那就是升级系统到2.3+。如若必须支持2.2,以下提供workaround和solution各一。
    有一个我验证可用的workaround:那就是用Socket的setSoTimeout方法来避免不限时的阻塞读。代码如下:
    Socket mTcpSocket = null;
      boolean mRunningFlag = false;
      public void recvThread() {
            Log.d("recvThread", "recvThread start");
            try {
                  mTcpSocket.setSoTimeout(1000); // 超时时长,越短越灵敏,但开销也越大
                  InputStream in = mTcpSocket.getInputStream();
                  while (mRunningFlag) {
                        byte[] data = new byte[1024];
                        try {
                              int len = in.read(data);
                                      if (len < 0) {
                                              throw new IOException("remote close socket");
                                      }
                              Log.d("recvThread", "" + len); // 这边应替换为处理代码
                        } catch (SocketTimeoutException e) {
                              // ignore
                        }
                  }
                  in.close();
            } catch (IOException e) {
                      Log.d("recvThread", e.getMessage());
            } finally {
                      // 记得清理!
                    Log.d("recvThread", "recvThread stop");
              }
      }
    关闭连接的时候就类似这样:
    mRunningFlag = false;
    mRecvThread.join();
    workaround的运行开销比较大。我觉得更好且更优雅的解决方案是:增加一种消息格式,客户端发送给服务端后,服务端主动关闭连接,之后客户端的接收线程将会抛出IOException,这样就不会阻塞住了。ps:即使不是为了规避这个Bug,也建议客户端断开连接时采用这种方式,因为这样才能保证所有数据都已经发给服务器。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值