简体   繁体   English

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

[英]Using Socket.IO on android Always Returns XHR Poll Error

I am writing an android app that needs to connect to a Socket.IO instance running on a node.js server.我正在编写一个需要连接到在 node.js 服务器上运行的 Socket.IO 实例的 android 应用程序。

Attempting to connect to the instance and transmitting data using an iOS device works flawlessly, but when I try to do it with an android device it fails.尝试连接到实例并使用 iOS 设备传输数据可以完美运行,但是当我尝试使用 Android 设备进行连接时却失败了。

I am using the Native java client , and this is the code I'm using on the android side:我正在使用本机 java 客户端,这是我在 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();

Whenever I try to connect (Basically as soon as the line mSocket.connect(); ) The log prints the following lines:每当我尝试连接时(基本上只要行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

So I immediately get an xhr poll error after attempting to connect and all following connection attempts meet the same result.所以我在尝试连接后立即收到 xhr 轮询错误,并且所有后续连接尝试都遇到相同的结果。

I saw some posts saying such an issue might be cause by an SSL certificate issue though any attempts I made to temper with the SSL Context the Socket.IO library uses didn't work.我看到一些帖子说这样的问题可能是由 SSL 证书问题引起的,尽管我为调整 Socket.IO 库使用的 SSL 上下文所做的任何尝试都没有奏效。

If anyoen has an idea what I might be able to try to get this to work it would be excellent.如果任何人知道我可以尝试使它起作用,那将是非常好的。

If any information or code sampels are missing, let me know and I'll add them.如果缺少任何信息或代码示例,请告诉我,我会添加它们。

After further testing I found the following:经过进一步测试,我发现了以下内容:

  1. If you debug your socket when you encounter different events (ie EVENT_ERROR), the exception you catch will contain the response code received from the address you tried to reach.如果您在遇到不同的事件(即 EVENT_ERROR)时调试套接字,您捕获的异常将包含从您试图到达的地址收到的响应代码。
  2. In my case when attempting to reach my server with HTTP I received a 301 response code because the URL I tried reaching automatically redirected me to the HTTPS address.在我的例子中,当我尝试使用 HTTP 访问我的服务器时,我收到了 301 响应代码,因为我尝试访问的 URL 自动将我重定向到 HTTPS 地址。
  3. When attempting to reach the HTTPS address I received a 401 response code - meaning the request my socket made had reached the server but was not authorized - The reason for that was that the target server had basic authentication turned on and I didn't supply the required credentials in the socket request headers.当尝试到达 HTTPS 地址时,我收到了一个 401 响应代码——这意味着我的套接字发出的请求已经到达服务器但未被授权——原因是目标服务器打开了基本身份验证,而我没有提供套接字请求标头中所需的凭据。
  4. After supplying the required headers I managed to connect to the socket server properly, but when sending out a request it failed and my socket went back to a re-connection attempt loop - The reason for that was that the JSON I sent to the server from my Android phone was not in the format expected and the server failed to receive that request.在提供了所需的标头后,我设法正确连接到套接字服务器,但是在发送请求时它失败了,我的套接字又回到了重新连接尝试循环——原因是我从 JSON 发送到服务器我的 Android 手机不是预期的格式,服务器未能收到该请求。

The code I used to add a basic authentication header to my socket request:我用来向我的套接字请求添加基本身份验证标头的代码:

// 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=="));
            }
        });
    }
});

If you encounter and XHR Poll error when you attempt to use Socket.IO, make sure that the connection to your socket server is available and that you are connecting properly.如果您在尝试使用 Socket.IO 时遇到 XHR 轮询错误,请确保与套接字服务器的连接可用并且连接正确。 In the end in my case it all revolved around the server requiring basic authentication and me not supplying it when contacting the server.最后,在我的案例中,一切都围绕着需要基本身份验证的服务器展开,而我在联系服务器时没有提供它。

Also , because I encountered that solution qutie a bit while trying to sovle this issue - When trying to reach your server over HTTPS, you usually don't need a special hostname verifier or special certificate manager.此外,因为我在尝试解决此问题时遇到了一些解决方案 - 当尝试通过 HTTPS 访问您的服务器时,您通常不需要特殊的主机名验证程序或特殊的证书管理器。 Try and avoid such solutions as they greatly harm the security of your app.尽量避免此类解决方案,因为它们会极大地损害您应用程序的安全性。

I can verify similar issue with my situation.我可以用我的情况验证类似的问题。 I am testing websocket connection to a development server.我正在测试与开发服务器的 websocket 连接。 No SSL, just plain http.没有 SSL,只有普通的 http。 Here was my situation:这是我的情况:

  1. Tested the apps websocket connection to dev server using android studio simulator - connected successfully made with no error.使用 android studio 模拟器测试应用程序 websocket 连接到开发服务器 - 连接成功,没有错误。
  2. Tested no.测试没有。 (1) above with real device instead of simulator. (1) 以上用真机代替模拟器。 Failed with the "xhr poll error" message.失败并显示"xhr poll error"消息。
  3. Then, after so much time with no success, I added in AndroidManifest.xml the following:然后,经过这么多时间没有成功,我在AndroidManifest.xml中添加了以下内容:

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

My project is currently targeting API 28, hence default for "usesCleartextTraffic" is false.我的项目当前针对 API 28,因此"usesCleartextTraffic"的默认值为 false。 Now everything is working fine.现在一切正常。

This will also happen if you forgot to set transport in options如果您忘记在选项中设置传输,也会发生这种情况

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

Also check whether your grant还要检查您的补助金是否

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

in manifest.xmlmanifest.xml

also add还添加

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

You have to add this code in application tag in the manifest as below:您必须在清单中的应用程序标记中添加此代码,如下所示:

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

i used your code and was having the exact same output, but your resolution didn't solve it for me.我使用了您的代码并得到了完全相同的输出,但是您的解决方案并没有为我解决问题。 The solution i found was to emit data every X seconds, basically the connection dropped if there was no data being sent.我找到的解决方案是每 X 秒发送一次数据,如果没有数据发送,基本上连接就会断开。

I didn't had to do any authorization.我不需要做任何授权。

The code is exactly as above the EVENT_TRANSPORT part and the EVENT_CONNECT is as follows:代码和上面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);

            }
        })

I just wanted to leave this here, it might help someone in the future, believe it or not, this was a nasty one to solve, the "xhr poll error" is very vague and a lot of different things can lead to it.我只是想把它留在这里,它可能会在将来帮助某人,信不信由你,这是一个很难解决的问题,“xhr poll error”非常模糊,很多不同的事情都可能导致它。 After trying so many different things, this simple code solved it.在尝试了很多不同的事情之后,这个简单的代码解决了它。

make sure your server accept websocket and polling in trans确保你的服务器接受 websocket 和轮询

   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"],
        }
    })

then disable antivirus然后禁用杀毒软件

Recently, I was facing issue "nodejs Error: xhr poll error"最近,我遇到了“nodejs 错误:xhr 轮询错误”问题

This error got fixed by:- Since my client(browser) was being hitted using http protocol as was working on my local but server was created using https protocol.此错误已通过以下方式修复:- 因为我的客户端(浏览器)正在使用 http 协议进行攻击,就像在我的本地工作一样,但服务器是使用 https 协议创建的。

So, temporary to work changed https to http.因此,临时工作将 https 更改为 http。

And before deploying code I changed back http to https as on live client will be hitted using https protocol.在部署代码之前,我将 http 更改回 https,因为在实时客户端上将使用 https 协议进行攻击。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM