在 android 上使用 Socket.IO 总是返回 XHR 轮询错误

Posted

技术标签:

【中文标题】在 android 上使用 Socket.IO 总是返回 XHR 轮询错误【英文标题】:Using Socket.IO on android Always Returns XHR Poll Error 【发布时间】:2016-09-02 18:10:35 【问题描述】:

我正在编写一个需要连接到在 node.js 服务器上运行的 Socket.IO 实例的 android 应用程序。

尝试使用 ios 设备连接到实例并传输数据完美无缺,但是当我尝试使用 android 设备进行时却失败了。

我正在使用Native java client,这是我在 android 端使用的代码:

mManager = new Manager(new URI("https://example.com"));
mSocket = mManager.socket("/users");

// socket events listeners
    mSocket.on(Socket.EVENT_CONNECTING, new Emitter.Listener() 
        @Override
        public void call(Object... args) 
            Log.v(TAG, "Caught EVENT_CONNECTING");
            for (Object obj : args) 
                Log.v(TAG, "Errors :: " + obj);
            
        
    ).on(Socket.EVENT_CONNECT, new Emitter.Listener() 
        @Override
        public void call(Object... args) 
            Log.v(TAG, "connected to the backend");
            Log.v(TAG, String.format("JSON Obj to emit: %s", jsonObject.toString()));
            mSocket.emit("hello_packet", jsonObject);
        
    ).on(Socket.EVENT_RECONNECTING, new Emitter.Listener() 
        @Override
        public void call(Object... args) 
            Log.v(TAG, "Caught EVENT_RECONNECTING");
            for (Object obj : args) 
                Log.v(TAG, "Errors :: " + obj);
            
        
    ).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() 
        @Override
        public void call(Object... args) 
            Log.v(TAG, "Socket disconnected");
        
    ).on(Socket.EVENT_ERROR, new Emitter.Listener() 
        @Override
        public void call(Object... args) 
            Log.v(TAG, "Caught EVENT_ERROR");
            for (Object obj : args) 
                Log.v(TAG, "Errors :: " + obj);
            
        
    ).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() 
        @Override
        public void call(Object... args) 
            Log.v(TAG, "Caught EVENT_CONNECT_ERROR");
            for (Object obj : args) 
                Log.v(TAG, "Errors :: " + obj);
            
        
    );

    Log.v(TAG, "Connecting socket");
    mSocket.connect();

每当我尝试连接时(基本上只要mSocket.connect(); 行),日志就会打印以下行:

05-07 22:41:36.684 15552-15552/com.my.app V/Main Activity: Connecting socket
05-07 22:41:36.699 15552-15858/com.my.app V/Main Activity: Caught EVENT_CONNECTING
05-07 22:41:36.926 15552-15866/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:36.926 15552-15866/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:38.189 15552-15884/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:38.189 15552-15884/com.my.app V/Main Activity: Errors :: 1
05-07 22:41:38.207 15552-15887/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:38.208 15552-15887/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:39.518 15552-15911/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:39.518 15552-15911/com.my.app V/Main Activity: Errors :: 2
05-07 22:41:39.531 15552-15915/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:39.531 15552-15915/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:41.846 15552-15949/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:41.846 15552-15949/com.my.app V/Main Activity: Errors :: 3
05-07 22:41:41.857 15552-15953/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:41.857 15552-15953/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:46.863 15552-16025/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:46.864 15552-16025/com.my.app V/Main Activity: Errors :: 4
05-07 22:41:46.879 15552-16029/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:46.879 15552-16029/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:51.883 15552-16126/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:51.883 15552-16126/com.my.app V/Main Activity: Errors :: 5
05-07 22:41:51.895 15552-16130/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:51.895 15552-16130/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:56.900 15552-16236/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:56.900 15552-16236/com.my.app V/Main Activity: Errors :: 6
05-07 22:41:56.921 15552-16240/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:56.921 15552-16240/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:01.927 15552-16357/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:01.927 15552-16357/com.my.app V/Main Activity: Errors :: 7
05-07 22:42:01.945 15552-16361/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:01.945 15552-16361/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:06.951 15552-16466/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:06.952 15552-16466/com.my.app V/Main Activity: Errors :: 8
05-07 22:42:06.969 15552-16470/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:06.970 15552-16470/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:11.975 15552-16545/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:11.976 15552-16545/com.my.app V/Main Activity: Errors :: 9
05-07 22:42:11.994 15552-16549/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:11.994 15552-16549/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:17.000 15552-16629/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:17.000 15552-16629/com.my.app V/Main Activity: Errors :: 10
05-07 22:42:17.012 15552-16633/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:17.012 15552-16633/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:22.017 15552-16710/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:22.017 15552-16710/com.my.app V/Main Activity: Errors :: 11
05-07 22:42:22.033 15552-16714/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:22.033 15552-16714/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:27.039 15552-16788/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:27.039 15552-16788/com.my.app V/Main Activity: Errors :: 12
05-07 22:42:27.056 15552-16792/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:27.056 15552-16792/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:32.061 15552-16957/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:32.062 15552-16957/com.my.app V/Main Activity: Errors :: 13

所以我在尝试连接后立即收到 xhr poll 错误,并且所有后续连接尝试都遇到相同的结果。

我看到一些帖子说这样的问题可能是由 SSL 证书问题引起的,尽管我对 Socket.IO 库使用的 SSL 上下文进行的任何尝试都没有奏效。

如果有人知道我可以尝试什么来让它工作,那就太好了。

如果缺少任何信息或代码示例,请告诉我,我会添加它们。

【问题讨论】:

【参考方案1】:

经过进一步测试,我发现了以下内容:

    如果您在遇到不同事件(即 EVENT_ERROR)时调试套接字,您捕获的异常将包含从您尝试到达的地址收到的响应代码。 在我尝试使用 HTTP 访问我的服务器时,我收到了 301 响应代码,因为我尝试访问的 URL 自动将我重定向到 HTTPS 地址。 在尝试访问 HTTPS 地址时,我收到了 401 响应代码 - 这意味着我的套接字发出的请求已到达服务器但未获得授权 - 原因是目标服务器打开了基本身份验证 并且我没有在套接字请求标头中提供所需的凭据。 提供所需的标头后,我设法正确连接到套接字服务器,但是在发出请求时失败,并且我的套接字返回到重新连接尝试循环 - 原因是我发送到的 JSON我的 Android 手机中的服务器不是预期的格式,服务器未能接收到该请求。

我用来向我的套接字请求添加基本身份验证标头的代码:

// Adding authentication headers when encountering EVENT_TRANSPORT
mSocket.io().on(Manager.EVENT_TRANSPORT, new Emitter.Listener() 
    @Override
    public void call(Object... args) 
        Transport transport = (Transport) args[0];
        // Adding headers when EVENT_REQUEST_HEADERS is called
        transport.on(Transport.EVENT_REQUEST_HEADERS, new Emitter.Listener() 
            @Override
            public void call(Object... args) 
                Log.v(TAG, "Caught EVENT_REQUEST_HEADERS after EVENT_TRANSPORT, adding headers");
                Map<String, List<String>> mHeaders = (Map<String, List<String>>)args[0];
                mHeaders.put("Authorization", Arrays.asList("Basic bXl1c2VyOm15cGFzczEyMw=="));
            
        );
    
);

如果您在尝试使用 Socket.IO 时遇到 XHR Poll 错误,请确保与您的套接字服务器的连接可用并且连接正确。最后,就我而言,这一切都围绕着需要基本身份验证的服务器而我在联系服务器时没有提供它。

另外,因为我在尝试解决此问题时遇到了相当多的解决方案 - 当尝试通过 HTTPS 访问您的服务器时,您通常 不需要特殊的主机名验证器或特殊的证书管理器。尽量避免此类解决方案,因为它们会极大地损害您应用的安全性。

【讨论】:

这解决了我的问题。无论如何,我一直在怀疑,因为通过浏览器的连接很好,它正在添加身份验证标头。谢谢。【参考方案2】:

我可以根据我的情况验证类似的问题。我正在测试与开发服务器的 websocket 连接。没有 SSL,只有普通的 http。这是我的情况:

    使用 android studio 模拟器测试了应用程序 websocket 与开发服务器的连接 - 连接成功,没有错误。 测试编号(1) 以上用真机代替模拟器。 "xhr poll error" 消息失败。

    然后,经过这么长时间没有成功,我在AndroidManifest.xml 中添加了以下内容:

    <application ... android:usesCleartextTraffic="true" ...>

我的项目目前针对 API 28,因此 "usesCleartextTraffic" 的默认值为 false。现在一切正常。

【讨论】:

这真的很有帮助。我遇到了同样的错误并且没有线索了......谢谢@YazidEF 谢谢您,先生,您确实为我节省了数小时的时间来寻找我的套接字客户端无法连接的原因!【参考方案3】:

如果您忘记在选项中设置传输,也会发生这种情况

IO.Options opts = new IO.Options();
opts.transports = new String[]WebSocket.NAME; //or Polling.NAME 

【讨论】:

【参考方案4】:

您必须在清单中的应用程序标记中添加此代码,如下所示:

<application 
   ... 
   android:usesCleartextTraffic="true">
    .... 
<application/>

【讨论】:

【参考方案5】:

还要检查您的授权是否

<uses-permission android:name="android.permission.INTERNET" />

manifest.xml

还加

<application 
   ... 
   android:usesCleartextTraffic="true">
    .... 
<application/>

【讨论】:

【参考方案6】:

我使用了您的代码并且得到了完全相同的输出,但您的解决方案并没有为我解决问题。我找到的解决方案是每 X 秒发送一次数据,如果没有发送数据,基本上连接会断开。

我不需要做任何授权。

代码与上面的EVENT_TRANSPORT部分完全一样,EVENT_CONNECT如下:

socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() 
            @Override
            public void call(Object... args) 
                Log.d("mylogs", "Socket: Web socket opened");

                Runnable runnable = new Runnable() 
                    @Override
                    public void run() 

                        socket.emit("YOUR_TOPIC", "YOUR_DATA_VALUE");

                        handler.postDelayed(this, 1000);
                    
                ;
                handler.post(runnable);

            
        )

我只是想把它留在这里,它可能会在未来对某人有所帮助,信不信由你,这是一个很难解决的问题,“xhr poll error”非常模糊,很多不同的事情都会导致它。在尝试了这么多不同的事情之后,这个简单的代码解决了它。

【讨论】:

【参考方案7】:

确保您的服务器接受 websocket 并在 trans 中轮询

   global.io = new ioServer.Server(server, 
        maxHttpBufferSize: 100000000,
        connectTimeout: 5000,
        transports:['websocket','polling'],
        pingInterval: 25 * 1000,
        pingTimeout: 5000,
        allowEIO3: true,
        cors: 
            origin: "http://localhost:3000",
            methods: ["GET", "POST"],
        
    )

然后禁用杀毒软件

【讨论】:

【参考方案8】:

最近,我遇到了问题“nodejs Error: xhr poll error”

此错误已通过以下方式修复:- 由于我的客户端(浏览器)是使用 http 协议访问的,就像在我的本地上工作一样,但服务器是使用 https 协议创建的。

因此,临时工作将 https 更改为 http。

在部署代码之前,我将 http 改回 https,因为在实时客户端上将使用 https 协议进行访问。

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于在 android 上使用 Socket.IO 总是返回 XHR 轮询错误的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 上发出 socket.io 消息

在 android 上使用 Socket.IO 总是返回 XHR 轮询错误

如何在 android 上检查 socket.io 连接或断开连接?

使用 HTTPS 协议的 android 连接中的 Socket.io 客户端失败?

从android与socket.io通信

Socket.io 无法在 Android 9(API 级别 28)上运行