美文网首页
Android WebSocket(socket.io)遇到的坑

Android WebSocket(socket.io)遇到的坑

作者: d26168ad953a | 来源:发表于2017-11-03 11:11 被阅读1964次

    一、导包如下

        //compile 'com.github.nkzawa:socket.io-client:0.3.0'//已过时,仅用于聊天Socket连接(js变种版websocket)
        compile ('io.socket:socket.io-client:0.8.3') {//最新包
            exclude group: 'org.json', module: 'json' //处理: WARNING: Dependency org.json:json:20090211 is ignored
        }
    

    PS:配置参考地址:https://socket.io/blog/native-socket-io-and-android/

    二、发送消息

        /**
         * Emits an event. When you pass {@link Ack} at the last argument, then the acknowledge is done.
         *
         * @param event an event name.
         * @param args data to send.
         * @return a reference to this object.
         */
        public Emitter emit(final String event, final Object... args){
            ...
        }
    

    上面的方法一些正常,下面还以一个带Ack监听

    /**
         * Emits an event with an acknowledge.
         *
         * @param event an event name
         * @param args data to send.
         * @param ack the acknowledgement to be called
         * @return a reference to this object.
         */
        public Emitter emit(final String event, final Object[] args, final Ack ack) {
            ...
        }
    

    在demo是一切正常,连接正常,登录正常,登录有回调的。但是正式的出问题了。

                //Socket绑定监听
                mSocket.on(Socket.EVENT_CONNECT, onConnect);
                mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
                mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
                mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
                //mSocket.io().on(Manager.EVENT_TRANSPORT, trans);//网上说SSL出问题,但是问题没有得到处理
    
                mSocket.on(EVENT_MSG, msg);
                mSocket.connect();
    
    1、流程:

    ①、在onConnect连接成功,②、emit(event, objects[], ack)发送登录信息msg

    2、问题:

    发送的登录信息msg用户名是英文没有任何问题,奇葩来了,如果含有中文则调onDisconnect监听断开连接,打印args[0].toString():transport error。
      关键的是接口同事打印,收到并解析 登录信息 成功,也给回包了。

    3、处理bug:

    首先想到的包的问题是否过时,替换最新的依然是:外甥打灯笼---照舅。
      然后就开始百度生涯:android io.socket disconnect transport error

    不负有心人,找到如下几个当时认为可用的,确实也收到启发。
    https://stackoverflow.com/questions/29073746/socket-io-disconnect-event-transport-close-client-namespace-disconnect
    https://stackoverflow.com/questions/37093221/using-socket-io-on-android-always-returns-xhr-poll-error
    官网:https://socket.io/docs/client-api/
    但问题没有解决,已经到快到十点了,还是明天处理。换一个思路打断点监听onDisconnect,找出的问题发生的时间点。

    打断点查看一步步的流程:
    又发生了奇葩的问题,打断点时候有时能收到登录成功的回调,有时收不到。查找源码

    
        /**
         * Emits an event with an acknowledge.
         *
         * @param event an event name
         * @param args data to send.
         * @param ack the acknowledgement to be called
         * @return a reference to this object.
         */
        public Emitter emit(final String event, final Object[] args, final Ack ack) {
            EventThread.exec(new Runnable() {
                @Override
                public void run() {
                    List<Object> _args = new ArrayList<Object>() {{
                        add(event);
                        if (args != null) {
                            addAll(Arrays.asList(args));
                        }
                    }};
                    
                    JSONArray jsonArgs = new JSONArray();
                    for (Object _arg : _args) {
                        jsonArgs.put(_arg);
                    }
                    int parserType = HasBinary.hasBinary(jsonArgs) ? Parser.BINARY_EVENT : Parser.EVENT;
                    Packet<JSONArray> packet = new Packet<JSONArray>(parserType, jsonArgs);
    
                    logger.fine(String.format("emitting packet with ack id %d", ids));
                    Socket.this.acks.put(ids, ack);
                    packet.id = ids++;
    
                    Socket.this.packet(packet);
                }
            });
            return this;
        }
    

    有时走到add(event);有时走到addAll(Arrays.asList(args));断开连接onDisconnect,又一次偶尔停顿了一下,Ack 有反应,收到的回包。预感问题找到了。又跑一次,debug慢点,Ack 收到登录回包;再次验证,Ack 都有回包。狂喜,问题找到了,哈哈哈!!!
    这属于线程间的异步通信问题,(PS:volatile原子性问题,32位的不会出现,但是64位的就会出现。这就解释了字母正常,汉字不正常)
    处理方法如下:

    new Thread(){
           @Override
           public void run() {
                 try {
                    Thread.sleep(400);//延迟发送
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mSocket.emit(EVENT, new Object[]{loginMsg()},  ack);
            }
    }.start();
    

    PS:正如前面所说有两种发送消息的方法,带Ack监听要特殊处理一下。

    public Emitter emit(final String event, final Object... args)
    public Emitter emit(final String event, final Object[] args, final Ack ack)
    

    总结

    debug断点调试要勤用,还有log打印日志。

    写于此以记心绪。
    .
    纯纯干货兴味索然
    感谢阅读收获归你
    不妥之处敬请指教

    加我微信 共同探讨

    .
    .
    .
    .
    .
    .
    .

    相关文章

      网友评论

          本文标题:Android WebSocket(socket.io)遇到的坑

          本文链接:https://www.haomeiwen.com/subject/dwnzpxtx.html