【问题标题】:Emit or Ack timeout handling in Android socket.IO ?Android socket.IO 中的 Emit 或 Ack 超时处理?
【发布时间】:2018-07-05 14:14:27
【问题描述】:

当使用socket.io 发出带有回调的消息时,如果套接字在回答之前断开连接(或根本不回答),则回调函数将永远挂起。在其他网络连接性较低且发出套接字但存在的情况下如果发射成功,则没有回调。

在这些情况下,我想在发出回调中实现超时。但是 ACK 消息没有超时。

这是我的套接字发射代码ACK

    JSONObject obj = new JSONObject();
    try {

        obj.put("device_id", deviceVO.getDeviceId());
        obj.put("device_status", deviceVO.getOldStatus());

    } catch (JSONException e) {
        e.printStackTrace();
    }

   mSocket.emit("socketChangeDevice", obj, new Ack() {
            @Override
            public void call(Object... args) {
                if(args!=null){
                    Ack ack = (Ack) args[args.length - 1];
                    ack.call();
                    Log.d("ACK_SOCKET","isAck : "+ ack);
                }
            }
        });

有没有更好的方法在客户端断开连接时返回失败的回调?我需要手动实现超时吗?

【问题讨论】:

    标签: android socket.io


    【解决方案1】:

    使用套接字发出的超时 ACK

    我的AckWithTimeOut自定义超时类实现Ack接口

    public class AckWithTimeOut implements Ack {
    
    private Timer timer;
    private long timeOut = 0;
    private boolean called = false;
    
    public AckWithTimeOut() {
    }
    
    public AckWithTimeOut(long timeout_after) {
        if (timeout_after <= 0)
            return;
        this.timeOut = timeout_after;
        startTimer();
    }
    
    public void startTimer() {
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                callback("No Ack");
            }
        }, timeOut);
    }
    
    public void resetTimer() {
        if (timer != null) {
            timer.cancel();
            startTimer();
        }
    }
    
    public void cancelTimer() {
        if (timer != null)
            timer.cancel();
    }
    
    void callback(Object... args) {
        if (called) return;
        called = true;
        cancelTimer();
        call(args);
    }
    
    @Override
    public void call(Object... args) {
    
    }
    }
    

    在套接字发射监听器中添加AckWithTimeOut

     mSocket.emit("socketChangeDeviceAck", obj, new AckWithTimeOut(5000) {
                @Override
                public void call(Object... args) {
                    if(args!=null){
                        if(args[0].toString().equalsIgnoreCase("No Ack")){
                            Log.d("ACK_SOCKET","AckWithTimeOut : "+ args[0].toString());
                        }else if(args[0].toString().equalsIgnoreCase("true")){
                           cancelTimer(); //cancel timer if emit ACK return true
                           Log.d("ACK_SOCKET","AckWithTimeOut : "+ args[0].toString());
                        }
                    }
                }
            });
    

    【讨论】:

      【解决方案2】:

      Kotlin 实现

      class AckWithTimeout(
          private var onSuccess: (args: Array<out Any>) -> Unit,
          private var onTimeout: () -> Unit,
          private val timeoutInMillis: Long
      ) : Ack {
          private var called = false
      
          private val timer: Timer = Timer().apply {
              schedule(object : TimerTask() {
                  override fun run() {
                      if (called) return
                      called = true
      
                      onTimeout()
                  }
              }, timeoutInMillis)
          }
      
          override fun call(vararg args: Any) {
              if (called) return
              called = true
              timer.cancel()
      
              onSuccess(args)
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-03
        相关资源
        最近更新 更多