【问题标题】:Android Socket.IO implementation can't connect to Express server running Socket.IO - Wireshark shows an HTTP 400/ Bad Request?Android Socket.IO 实现无法连接到运行 Socket.IO 的 Express 服务器 - Wireshark 显示 HTTP 400/错误请求?
【发布时间】:2021-05-24 22:56:29
【问题描述】:

我正在尝试使用 Native Socket.IO 将 Android 应用程序连接到 Express 服务器。服务器有一个非常简单的工作(目前),接收 4200 上的传入流量并将其发送回其他客户端,以便他们可以显示它 - 尽管现在我只是调试服务器和这个 Android 实现,希望得到漂亮的文本“客户端已连接”

这是服务器 API

// Socket handling
io.on( 'connection', (socket) => {
    console.log('Client Connected');
  
    socket.on('temperature', (data) => {
      console.log('Engine Data:' + data);
      // For now, just spit data back to all other connected clients
      socket.broadcast.emit('temperature', {num: data});
    });
  
    socket.on('disconnect', ()=> {
      console.log('Client disconnected');
    });
});

目前这适用于发送随机数的基本 Node.JS 客户端,所以我知道服务器可以正常工作:

    <script>
        var socket = io('http://localhost:4200');

        socket.on('connection',  (socket) => {
            console.log('Connection Success');
        });

        let temperature = 0;
        //Send stuff every 100ms
        setInterval(() => {
            let lastTemp = temperature < 90 ? temperature : 0;
            temperature = Math.floor(Math.random() * 5) + lastTemp;

            socket.emit('temperature', temperature);
        }, 50);
    </script>

但是我的 Android 应用程序有问题 - 服务器没有像浏览器客户端那样记录连接,虽然它没有在连接上引发异常,但套接字 ID 只是 NULL 并且状态是“不调试时已连接”。我一直在关注不同的tutorials 并尝试在 StackOverflow 上发布解决方案,因此我目前的主要活动是利用搜索栏获取如下所示的虚拟值:

//! SocketIO stuff
import com.github.nkzawa.socketio.client.IO
import com.github.nkzawa.socketio.client.Socket


 class MainActivity : AppCompatActivity() {
    //! Instantiate socket for other functions that will utilize it - this will likely be part of its own class
    lateinit var mSocket: Socket

    //! Main Activity creation
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(findViewById(R.id.toolbar))

        //! SeekBar for setting dummy input by user
        val seek: SeekBar = findViewById<SeekBar>(R.id.seekBar)
        seek.max = 100
        seek.progress = 50

        //! CurrentVal is our current dummy sensor value
        var currentVal: Int;

        //! Connect to web server
        try {
            //! Configure library options
            val options = IO.Options()
            options.reconnection = true
            options.forceNew = true
            //This address is the way you can connect to localhost with AVD(Android Virtual Device)
            mSocket = IO.socket("http://10.0.2.2:4200/", options) // emulator loopback address
        } catch (e: Exception) {
            e.printStackTrace()
            Log.d("Failure", "Failed to connect to server")
        }
        Log.d("Connected", "socket ID:${mSocket.id()}")
        mSocket.connect()
        seek.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
...
            override fun onStopTrackingTouch(seek: SeekBar) {
                //Progress stopped
                //get value from seek bar
                currentVal = seek.progress
                //Send the value via our socket
                mSocket.emit("temperature", currentVal)
            }
        })
    }

根据其他 StackOverflow 建议的反馈,我的清单包括以下内容

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application
        ...
        android:usesCleartextTraffic="true"
...

但是,服务器并未反映客户端已连接。当我查看 Wireshark 时,我看到确实有一个端口 55735 正在尝试连接到在 4200 上运行的服务器,但是服务器响应“400 Bad Request”并且 JSON 字符串值为“不支持的协议版本”

2899    23.395504   127.0.0.1   127.0.0.1   HTTP/JSON   287 HTTP/1.1 400 Bad Request , JavaScript Object Notation (application/json)

这让我相信我正在使用的 Socket.IO 库和服务器上的 Socket.IO 存在一些兼容性问题。我正在使用的教程在 Socket.IO 网站上......但它也是从 2015 年开始的。我应该按照不同的方式在 Android 上使用 Socket.IO 吗?

【问题讨论】:

  • 您的服务器在哪里运行?您的 Android 应用在哪里运行?
  • 我看到了 127.0.0.1 和 10.0.2.2,您可以向我们解释一下。
  • // emulator loopback address 127.0.0.1号也是模拟器环回地址。
  • //This address is the way you can connect to localhost with AVD(Android Virtual Device)。不。使用 10.0.2.2,模拟器上的客户端可以连接到运行模拟器的电脑上运行的服务器。
  • 服务器在 PC 上,Android 在同一台 PC 上的模拟器上运行。听起来我的地址是正确的......

标签: android node.js express sockets socket.io


【解决方案1】:

我似乎已经解决了这个问题 - Android 的 socket.io 库与 NPM 中的最新 3.1.1 不兼容

这主要通过观察 Wireshark 中的数据来显示 - 我在端口之间进行了通信,但是响应 - 主要是响应中的 JSON - 表明协议版本不正确

简而言之,应用程序的 build.gradle 文件中的依赖项(如 2015 年 Socket.IO 的原始教程中所示)已经过时了

implementation 'com.github.nkzawa:socket.io-client:0.6.0' 
//OUT OF DATE

Joyce Hong 的这个实现更接近...

implementation ('io.socket:socket.io-client:1.0.0') {
        exclude group: 'org.json', module: 'json'
    }
//Still nope, but that was a clue

但是,与我在 NPM 中的 3.1.1 Socket.IO 库兼容的实现是

implementation ('io.socket:socket.io-client:2.0.0') {
        exclude group: 'org.json', module: 'json'
    }
//YES

如果其他人在端口之间存在流量但都没有注册连接时遇到此问题,请检查您的版本

【讨论】:

    猜你喜欢
    • 2014-08-10
    • 1970-01-01
    • 2014-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多