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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37093221/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 02:12:13  来源:igfitidea点击:

Using Socket.IO on android Always Returns XHR Poll Error

javaandroidsocketswebsocketsocket.io

提问by Mor Paz

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:

我正在使用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();

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.

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

采纳答案by Mor Paz

After further testing I found the following:

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

  1. If you debug your socket when you encounter different events (i.e. EVENT_ERROR), the exception you catch will contain the response code received from the address you tried to reach.
  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.
  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 onand I didn't supply the required credentials in the socket request headers.
  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.
  1. 如果您在遇到不同的事件(即 EVENT_ERROR)时调试套接字,您捕获的异常将包含从您尝试访问的地址收到的响应代码。
  2. 在我尝试使用 HTTP 访问我的服务器时,我收到了 301 响应代码,因为我尝试访问的 URL 自动将我重定向到 HTTPS 地址。
  3. 在尝试访问 HTTPS 地址时,我收到了 401 响应代码 - 意味着我的套接字发出的请求已到达服务器但未获得授权 - 原因是目标服务器打开基本身份验证,而我没有提供套接字请求标头中所需的凭据。
  4. 提供所需的标头后,我设法正确连接到套接字服务器,但是在发送请求时它失败了,我的套接字返回到重新连接尝试循环 - 原因是我发送到服务器的 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. In the end in my case it all revolved around the server requiring basic authentication and me not supplying it when contacting the server.

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

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 needa special hostname verifier or special certificate manager. Try and avoid such solutions as they greatly harm the security of your app.

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

回答by Hymanson Chengalai

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 

回答by saeed shaikh

You have to add this code in application tag in the manifest as below :

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

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

回答by Ragesh D Antony

Also check whether your grant

还要检查您的赠款是否

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

in manifest.xml

manifest.xml

also add

还添加

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

回答by YazidEF

I can verify similar issue with my situation. I am testing websocket connection to a development server. No SSL, just plain http. Here was my situation:

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

  1. Tested the apps websocket connection to dev server using android studio simulator - connected successfully made with no error.
  2. Tested no. (1) above with real device instead of simulator. Failed with the "xhr poll error"message.
  3. Then, after so much time with no success, I added in AndroidManifest.xmlthe following:

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

  1. 使用 android studio 模拟器测试了应用程序 websocket 与开发服务器的连接 - 连接成功,没有错误。
  2. 测试没有。(1) 以上用真机代替模拟器。"xhr poll error"消息失败。
  3. 然后,经过这么多时间没有成功,我添加AndroidManifest.xml了以下内容:

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

My project is currently targeting API 28, hence default for "usesCleartextTraffic"is false. Now everything is working fine.

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

回答by Ricardo Abreu

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. After trying so many different things, this simple code solved it.

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