Ratchet PHP 服务器建立连接,但 Kotlin 从未收到确认

问题描述

我有一个棘轮服务器,我尝试通过 Websocket 访问它。它类似于教程:当有新客户端或收到消息时记录。 Ratchet 服务器报告已成功建立连接,而 Kotlin 客户端则没有(Kotlin 中的连接事件从未被触发)。我正在使用 socket-io-java 模块 v.2.0.1。客户端在指定的超时时间后显示超时,在服务器上分离并在一段时间后再次连接,就像它似乎认为的那样,连接没有正确连接(因为缺少连接响应?)。

如果客户端是 Chrome 的 JS 控制台中的 Websocket 客户端,而不是我的 Kotlin 应用程序,则成功的连接确认会报告给客户端。即使在同一台计算机上运行的 Android 模拟器也没有得到响应(所以我认为问题与 wi-fi 无关)。 该连接在 JS 上运行良好,完成了完整的握手,但在 Android 应用中,它只能到达服务器,而再也不会到达客户端。

这是我的服务器代码

<?PHP


namespace agroSMS\Websockets;


use Ratchet\ConnectionInterface;
use Ratchet\MessageComponentInterface;

class SocketConnection implements MessageComponentInterface
{
    protected \SplObjectStorage $clients;
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    function onopen(ConnectionInterface $conn)
    {
        $this->clients->attach($conn);
        error_log("New client attached");
    }

    function onClose(ConnectionInterface $conn)
    {
        $this->clients->detach($conn);
        error_log("Client detached");
    }

    function onError(ConnectionInterface $conn,\Exception $e)
    {
        echo "An error has occurred: {$e->getMessage()}\n";

        $conn->close();
    }

    function onMessage(ConnectionInterface $from,$msg)
    {
        error_log("Received message: $msg");
        // Todo: Implement onMessage() method.
    }
}

以及我在终端中运行的脚本:

<?PHP

use Ratchet\Server\IoServer;
use agroSMS\Websockets\SocketConnection;
use Ratchet\WebSocket\WsServer;
use Ratchet\Http\HttpServer;

require dirname(__DIR__) . '/vendor/autoload.PHP';

$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new SocketConnection()
        )
    )
);

$server->run();

我在浏览器中运行的测试(在 Chrome 中返回“已建立连接”,但由于某种原因不在浏览器“勇敢”中):

var conn = new WebSocket('ws://<my-ip>:80');
conn.onopen = function(e) {
    console.log("Connection established!");
};

conn.onmessage = function(e) {
    console.log(e.data);
};

我的 Kotlin 代码是什么样的:

try {
       val uri = URI.create("ws://<my-ip>:80")
       val options = IO.Options.builder()
                    .setTimeout(60000)
                    .setTransports(arrayOf(WebSocket.NAME))
                    .build()
       socket = IO.socket(uri,options)
       socket.connect()
                            .on(Socket.EVENT_CONNECT) {
                                Log.d(TAG,"[INFO] Connection established")
                                socket.send(jsonObject)
                            }
                            .once(Socket.EVENT_CONNECT_ERROR) {
                                val itString = gson.toJson(it)
                                Log.d(TAG,itString)
                            }
}catch(e : Exception) {
   Log.e(TAG,e.toString())
}

一分钟后,Kotlin 代码记录“超时”错误,从服务器分离,然后再次附加。 当我停止服务器上的脚本时,它会给出一个错误:“连接重置,websocket 错误”(这是有道理的,但为什么他没有第一次获得连接?)

我还尝试将 url 中的协议“只是”更改为“wss”,以防万一可能是问题所在,即使我的服务器甚至不能使用 SSL,但这只是给了我另一个错误

[{"cause":{"bytesTransferred":0,"detailMessage":"Read timed out","stackTrace":[],"suppressedExceptions":[]},"detailMessage":"websocket error","suppressedExceptions":[]}]

而且连接甚至没有在服务器上建立。所以这次尝试更像是降级。

解决方法

我去了socket.io-java-client的github页面,在那里找到了我的问题的解决方案,结果发现,整个问题是,我误解了一个非常重要的概念: socket.io 使用 Websockets 并不意味着它与 Websockets 兼容。 所以说清楚的话: 如果你在客户端使用 socket.io,你也需要在服务器端使用它,反之亦然。由于 socket.io 随其数据包发送了大量元数据,因此纯 Websocket 服务器将接受它们的连接建立,但 socket.io 客户端不会接受他返回的确认。 您必须使用完整的 socket.io 或完整的纯 Websocket。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...