当前位置: 首页 > 工具软件 > engine.io > 使用案例 >

socket.io使用之io.socket.engineio.client.EngineIOException: server error,parser error

习华灿
2023-12-01

项目中需要使用即时通讯模块,决定采用socket.io作为服务端模块,客户端采用socket.io-client-java。在开发过程中,测试环境均正常,但发布到服务器上时客户端却报告如下异常:

null,parser error
io.socket.engineio.client.EngineIOException: server error
    at io.socket.engineio.client.Socket.onPacket(Socket.java:507)
    at io.socket.engineio.client.Socket.access$1000(Socket.java:31)
    at io.socket.engineio.client.Socket$5.call(Socket.java:313)
    at io.socket.emitter.Emitter.emit(Emitter.java:117)
    at io.socket.engineio.client.Transport.onPacket(Transport.java:134)
    at io.socket.engineio.client.transports.Polling.access$700(Polling.java:17)
    at io.socket.engineio.client.transports.Polling$2.call(Polling.java:124)
    at io.socket.engineio.parser.Parser.decodePayload(Parser.java:184)
    at io.socket.engineio.client.transports.Polling._onData(Polling.java:132)
    at io.socket.engineio.client.transports.Polling.onData(Polling.java:101)
    at io.socket.engineio.client.transports.PollingXHR$5$1.run(PollingXHR.java:109)
    at io.socket.thread.EventThread$2.run(EventThread.java:80)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
EVENT_ERROR:[io.socket.engineio.client.EngineIOException: server error]

同时发现当返回数据中不包含中文时一切都正常。一开始以为是服务环境有问题,捣腾了好久,什么都改的跟测试环境一样,还是无法解决。于是决定调试客户端,发现服务器数据其实是返回给了客户端(早点打开客户端日志,也就没前面的瞎倒腾的了)在源码中发现在此处跑出了异常:

        public static void decodePayload(String data, DecodePayloadCallback<String> callback) {
        if (data == null || data.length() == 0) {
            callback.call(err, 0, 1);
            return;
        }

        StringBuilder length = new StringBuilder();
        for (int i = 0, l = data.length(); i < l; i++) {
            char chr = data.charAt(i);

            if (':' != chr) {
                length.append(chr);
            } else {
                int n;
                try {
                    n = Integer.parseInt(length.toString());
                } catch (NumberFormatException e) {
                    callback.call(err, 0, 1);
                    return;
                }

                String msg;
                try {
                    msg = data.substring(i + 1, i + 1 + n);
                } catch (IndexOutOfBoundsException e) {
                    callback.call(err, 0, 1);
                    return;
                }

                if (msg.length() != 0) {
                    Packet<String> packet = decodePacket(msg, true);//就是这句话抛出了  UTF8Exception(INVALID_CONTINUATION_BYTE)异常
                    if (err.type.equals(packet.type) && err.data.equals(packet.data)) {
                        callback.call(err, 0, 1);
                        return;
                    }

                    boolean ret = callback.call(packet, i + n, l);
                    if (!ret) return;
                }

                i += n;
                length = new StringBuilder();
            }
        }

        if (length.length() > 0) {
            callback.call(err, 0, 1);
        }
    }

decodePacket方法如下


    public static Packet<String> decodePacket(String data, boolean utf8decode) {
        int type;
        try {
            type = Character.getNumericValue(data.charAt(0));
        } catch (IndexOutOfBoundsException e) {
            type = -1;
        }

        if (utf8decode) {
            try {
                data = UTF8.decode(data);
            } catch (UTF8Exception e) {
                return err;
            }
        }

        if (type < 0 || type >= packetslist.size()) {
            return err;
        }

        if (data.length() > 1) {
            return new Packet<String>(packetslist.get(type), data.substring(1));
        } else {
            return new Packet<String>(packetslist.get(type));
        }
    }

通过简单分析了源码发现socket-client-java底层采用了websocket(依赖okhttp),PollingXHR(简单的理解为一种轮询),在websocket这条处理线路上decodePacket(String data, boolean utf8decode) 中的utf8decode为false,在polling上却是true。
调试过程发现在测试环境时数据居然走的是websocket,正式环境数据却是从polling过来,发现数据不需要UTF.decode(data)已经是正确,一解码反而产生了错误,于是下载源码修改utf8decode值为false,问题解决。
虽然问题好像暂时解决但还是有如下疑问:

  1. 为什么在正式环境数据是从polling过来而不是websocket
  2. 两种通讯方式是如何工作协调
  3. 服务器客户端详细的通讯流程

有时间再认真看看源码吧!

 类似资料: