簡體   English   中英

在 android 上使用 Socket.IO 總是返回 XHR 輪詢錯誤

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

我正在編寫一個需要連接到在 node.js 服務器上運行的 Socket.IO 實例的 android 應用程序。

嘗試連接到實例並使用 iOS 設備傳輸數據可以完美運行,但是當我嘗試使用 Android 設備進行連接時卻失敗了。

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

每當我嘗試連接時(基本上只要行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 輪詢錯誤,並且所有后續連接嘗試都遇到相同的結果。

我看到一些帖子說這樣的問題可能是由 SSL 證書問題引起的,盡管我為調整 Socket.IO 庫使用的 SSL 上下文所做的任何嘗試都沒有奏效。

如果任何人知道我可以嘗試使它起作用,那將是非常好的。

如果缺少任何信息或代碼示例,請告訴我,我會添加它們。

經過進一步測試,我發現了以下內容:

  1. 如果您在遇到不同的事件(即 EVENT_ERROR)時調試套接字,您捕獲的異常將包含從您試圖到達的地址收到的響應代碼。
  2. 在我的例子中,當我嘗試使用 HTTP 訪問我的服務器時,我收到了 301 響應代碼,因為我嘗試訪問的 URL 自動將我重定向到 HTTPS 地址。
  3. 當嘗試到達 HTTPS 地址時,我收到了一個 401 響應代碼——這意味着我的套接字發出的請求已經到達服務器但未被授權——原因是目標服務器打開了基本身份驗證,而我沒有提供套接字請求標頭中所需的憑據。
  4. 在提供了所需的標頭后,我設法正確連接到套接字服務器,但是在發送請求時它失敗了,我的套接字又回到了重新連接嘗試循環——原因是我從 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 輪詢錯誤,請確保與套接字服務器的連接可用並且連接正確。 最后,在我的案例中,一切都圍繞着需要基本身份驗證的服務器展開,而我在聯系服務器時沒有提供它。

此外,因為我在嘗試解決此問題時遇到了一些解決方案 - 當嘗試通過 HTTPS 訪問您的服務器時,您通常不需要特殊的主機名驗證程序或特殊的證書管理器。 盡量避免此類解決方案,因為它們會極大地損害您應用程序的安全性。

我可以用我的情況驗證類似的問題。 我正在測試與開發服務器的 websocket 連接。 沒有 SSL,只有普通的 http。 這是我的情況:

  1. 使用 android studio 模擬器測試應用程序 websocket 連接到開發服務器 - 連接成功,沒有錯誤。
  2. 測試沒有。 (1) 以上用真機代替模擬器。 失敗並顯示"xhr poll error"消息。
  3. 然后,經過這么多時間沒有成功,我在AndroidManifest.xml中添加了以下內容:

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

我的項目當前針對 API 28,因此"usesCleartextTraffic"的默認值為 false。 現在一切正常。

如果您忘記在選項中設置傳輸,也會發生這種情況

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

還要檢查您的補助金是否

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

manifest.xml

還添加

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

您必須在清單中的應用程序標記中添加此代碼,如下所示:

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

我使用了您的代碼並得到了完全相同的輸出,但是您的解決方案並沒有為我解決問題。 我找到的解決方案是每 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”非常模糊,很多不同的事情都可能導致它。 在嘗試了很多不同的事情之后,這個簡單的代碼解決了它。

確保你的服務器接受 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"],
        }
    })

然后禁用殺毒軟件

最近,我遇到了“nodejs 錯誤:xhr 輪詢錯誤”問題

此錯誤已通過以下方式修復:- 因為我的客戶端(瀏覽器)正在使用 http 協議進行攻擊,就像在我的本地工作一樣,但服務器是使用 https 協議創建的。

因此,臨時工作將 https 更改為 http。

在部署代碼之前,我將 http 更改回 https,因為在實時客戶端上將使用 https 協議進行攻擊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM