【问题标题】:PHP Websocket Detect If chat message is sent or notPHP Websocket检测是否发送聊天消息
【发布时间】:2016-09-09 11:10:46
【问题描述】:

我正在使用 Ratchet Websocket 库在移动应用程序上聊天。

我使用了以下代码:发送/接收消息:

class Chat implements MessageComponentInterface {
    protected $clients;

    public function __construct()
    {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn)
    {
        $this->clients->attach($conn);
        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg)
    {

        foreach ($this->clients as $client) {
            if ($from !== $client) {

                $client->send($msg);
            }
        }
    }

    public function onClose(ConnectionInterface $conn)
    {

        $this->clients->detach($conn);

        echo "Connection {$conn->resourceId} has disconnected\n";
    }

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

        $conn->close();
    }
}

在 iOS 上,当用户进入聊天屏幕时,我调用 Connection Open 来打开移动设备和 Web 之间的连接。但是当我断开 Wifi 时。在服务器上 OnClose 没有被调用。所以服务器没有收到当前连接断开的通知。当服务器向应用程序发送任何消息时,iOS 应用程序不会收到它。我想知道有什么方法可以在OnMessage 函数中检测到$client->send($msg) 是否实际发送?

【问题讨论】:

    标签: php ios websocket ratchet


    【解决方案1】:

    您必须记住的是,WebSocket 只是一个 TCP 套接字连接。这是一个可以在任一端终止的有状态套接字。

    连接终止阶段使用四次握手,连接的每一端独立终止。当一个端点希望停止它的一半连接时,它会发送一个 FIN 数据包,另一端用 ACK 确认该数据包。因此,典型的拆除需要来自每个 TCP 端点的一对 FIN 和 ACK 段。

    Source: Wikipedia - Transmission Control Protocol: 4.2 Connection Termination

    所以有两种方法可以终止这个套接字。

    1. 干净发送FIN数据包,另一端确认该请求,然后完成关闭握手。
    2. 不太干净,一端被从套接字中切断,而没有发送FIN 数据包来完成关闭握手。

    在您的情况下,断开 WiFi 意味着服务器可能没有收到来自客户端的任何此类关闭握手,并且将在最大允许超时时间内保持TIME_WAIT 状态。在达到此超时之前,服务器不知道连接已丢失。除非服务器尝试向这个客户端发送数据,否则会出现连接丢失错误,这也是超时的,因为数据包将被发送多次而没有得到另一端的确认,然后才确定客户肯定不在了。

    您无法从您的onMessage 回调中检测到这一点,但是您可以从您的onError 回调方法中检测到它。当服务器尝试向客户端发送数据但失败或发生超时时,异常会从这个回调中冒泡到您的应用程序代码中,您可以在其中捕获并适当地处理它。

    请记住,由于与客户端的不干净断开连接,此异常在实际发生超时之前不会出现。所以它不会立即发生,因为服务器不会立即知道它。

    【讨论】:

    • 感谢您的回答,那么我应该怎么做才能知道消息是否实际发送。有没有其他办法?
    • 从 onError 方法中捕获异常。这就是它的用途。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 2016-04-13
    • 2014-07-26
    相关资源
    最近更新 更多