You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin使用Socket.io时chat:enter事件收不到服务端ack

问题现象

已成功实现客户端与服务端的Socket.io连接,但存在异常:

  • chat:enter 事件在前端环境下运行正常,可正常收到服务端ack确认
  • 仅Android Kotlin实现中无法收到该事件的服务端应答
    相关实现代码如下:

Socket连接相关实现

fun connectWithChatServer(message: Message, onSocketIOEventListener: Listeners.OnSocketIOEventListener) {
    try {
        if (message.chatConnectionInfo != null) {
            val token: String = message.chatConnectionInfo?.token!!
            try {
                val opts = IO.Options()
                opts.forceNew = true
                opts.query = "{token : '$token'}"
                opts.transports = arrayOf("websocket")
                opts.path = "/chatsignal"
                mSocket = IO.socket(message.chatConnectionInfo?.connectionUrl.toString(), opts)
                makeConnection()
            } catch (e: Exception) {
                e.printStackTrace()
                Log.d("fail", "Failed to connect")
            }
        }
    } catch (e: URISyntaxException) {
        throw RuntimeException(e)
    }
}
private fun makeConnection() {
    if (mSocket != null) {
        mSocket?.connect()
        registerConnectionAttributes()
    }
}
private fun registerConnectionAttributes() {
    try {
        if (mSocket != null) {
            mSocket?.on(Socket.EVENT_CONNECT, onConnect)
           
        }
    } catch (e: java.lang.Exception) {
        e.printStackTrace()
    }
}

onConnect事件发送逻辑

private var onConnect = Emitter.Listener {
        mSocket!!.emit("chat:enter", "{}", Ack { args ->
            Constants.printDebug(logTag, "Ack ${args[0]}")
            val text = args[0].toString()
        })
    }
问题原因与修复方案

该问题由两个核心代码错误导致:

  1. query参数格式不符合规范
    当前代码中opts.query = "{token : '$token'}"传入的是JSON格式字符串,Socket.io客户端要求query参数必须为标准URL查询字符串格式(即key=value形式),错误的参数格式会导致服务端鉴权逻辑异常,部分事件处理流程无法正常触发。
    直接将该行修改为:
opts.query = "token=$token"
  1. 监听器注册顺序错误 + 传参类型不匹配
  • 当前逻辑先调用mSocket?.connect()再注册EVENT_CONNECT监听器,极端场景下连接成功事件会在监听器绑定前触发,导致onConnect逻辑根本没有执行
  • emit事件时传入的"{}"是字符串类型,和前端传入的空JSON对象类型不一致,多数服务端框架会因参数类型校验不通过,不返回ack响应

对应修复方式:

  • 调整执行顺序,先注册所有事件监听器,再发起连接
  • 使用原生JSONObject传递空参数对象,保证和前端传参类型一致

修复后的相关代码如下:

// 调整连接方法逻辑,先绑监听器再连接
private fun makeConnection() {
    if (mSocket != null) {
        registerConnectionAttributes()
        mSocket?.connect()
    }
}

// 修改emit传参类型
private var onConnect = Emitter.Listener {
    val emptyParams = org.json.JSONObject()
    mSocket!!.emit("chat:enter", emptyParams, Ack { args ->
        Constants.printDebug(logTag, "Ack ${args[0]}")
        val text = args[0].toString()
    })
}

额外排查项

  • 确认Android端使用的Socket.io客户端版本和服务端部署的Socket.io大版本完全一致,跨大版本会存在事件、ack的协议兼容问题
  • 补充绑定Socket.EVENT_CONNECT_ERROR、Socket.EVENT_ERROR事件监听器,打印错误日志排查是否存在隐式鉴权、连接异常

内容的提问来源于stack exchange,提问作者Ahmad Bhatti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 04:01:19