如何正确启动websocket Server?

时间:2018-08-13 17:50:43

标签: javascript php tcp websocket

我已经使用Ratchet在本地MAMP PRO环境中通过php设置了一个websocket服务器。

$server = IoServer::factory(
    new Control(),
    81,
    '0.0.0.0'
);

使用root特权启动服务器(因为除root特权外,我无法使他正常运行(权限被拒绝))

php server.php

建立连接

telnet 192.168.2.106 81
Trying 192.168.2.106...
Connected to mmm.mrmedia.private.

正确回答

php server.php
New connection! (37)

但是,如果我尝试通过JavaScript连接到服务器,则不会通过握手(过了一段时间后会出现ERR_CONNECTION_REFUSED)。

New connection! (48)
Connection 48 sending message "GET / HTTP/1.1
Host: 192.168.2.106:81
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Upgrade: websocket
Origin: http://192.168.2.106
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: de,de-DE;q=0.9,en;q=0.8,en-US;q=0.7,es;q=0.6,fr;q=0.5,it;q=0.4
Sec-WebSocket-Key: RH25+2UD8PQI+0A+VQWn4Q==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

控制台输出以下信息:

TIC TCP Conn Start [24126:0x7fdcc6f47c20]
TIC TCP Conn Event [24126:0x7fdcc6f47c20]: 3
TIC TCP Conn Failed [24126:0x7fdcc6f47c20]: 12:8 Err(-65554)
TIC TCP Conn Cancel [24126:0x7fdcc6f47c20]

源server.php

use Ratchet\Server\IoServer;
use FluvalEdge\Control;

    require dirname(__DIR__) . '/websocket-php-ratchet/vendor/autoload.php';

    $server = IoServer::factory(
        new Control(),
        81,
        '0.0.0.0'
    );

    $server->run();

源名称间隔FluvalEdge

namespace FluvalEdge;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class Control implements MessageComponentInterface {
    protected $clients;

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

    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);

        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
    }

    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        $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();
    }
}

通过调用客户端连接

initWebsocket('ws://192.168.2.106:81', false, 5000, 5);

源websocket.js

/**
 * inits a websocket by a given url, returned promise resolves with initialized websocket, rejects after failure/timeout.
 *
 * @param url the websocket url to init
 * @param existingWebsocket if passed and this passed websocket is already open, this existingWebsocket is resolved, no additional websocket is opened
 * @param timeoutMs the timeout in milliseconds for opening the websocket
 * @param numberOfRetries the number of times initializing the socket should be retried, if not specified or 0, no retries are made
 *        and a failure/timeout causes rejection of the returned promise
 * @return {Promise}
 */
function initWebsocket(url, existingWebsocket, timeoutMs, numberOfRetries) {
    timeoutMs = timeoutMs ? timeoutMs : 1500;
    numberOfRetries = numberOfRetries ? numberOfRetries : 0;
    var hasReturned = false;
    var promise = new Promise((resolve, reject) => {
        setTimeout(function () {
            if(!hasReturned) {
                console.info('opening websocket timed out: ' + url);
                rejectInternal();
            }
        }, timeoutMs);
        if (!existingWebsocket || existingWebsocket.readyState != existingWebsocket.OPEN) {
            if (existingWebsocket) {
                existingWebsocket.close();
            }
            var websocket = new WebSocket(url);
            websocket.onopen = function () {
                if(hasReturned) {
                    websocket.close();
                } else {
                    console.info('websocket to opened! url: ' + url);
                    resolve(websocket);
                }
            };
            websocket.onclose = function () {
                console.info('websocket closed! url: ' + url);
                rejectInternal();
            };
            websocket.onerror = function () {
                console.info('websocket error! url: ' + url);
                rejectInternal();
            };
        } else {
            resolve(existingWebsocket);
        }

        function rejectInternal() {
            if(numberOfRetries <= 0) {
                reject();
            } else if(!hasReturned) {
                hasReturned = true;
                console.info('retrying connection to websocket! url: ' + url + ', remaining retries: ' + (numberOfRetries-1));
                initWebsocket(url, null, timeoutMs, numberOfRetries-1).then(resolve, reject);
            }
        }
    });
    promise.then(function () {hasReturned = true;}, function () {hasReturned = true;});
    return promise;
};


/*
var ws_host_fluval = "fluvaledge.local";
var ws_port_fluval = "81";
var ws_server_fluval = "";
var ws_url_fluval = "ws://" + ws_host_fluval + ":" + ws_port_fluval + "/" + ws_server_fluval;

try
{
    var socket_fluval = new WebSocket(ws_url_fluval);

    // Handlerfunktionen definieren
    socket_fluval.onopen = function()
    {
        // Willkommensnachricht an den Server senden
        socket_fluval.send("Client hat Verbindung mit fluvaledge hergestellt");
    };

    socket_fluval.onmessage = function(msg)
    {
        console.log("Websocket: " + msg.data);
    };

    socket_fluval.onclose = function(msg)
    {
        console.log("Verbindung wurde getrennt");
    };
}
catch(ex)
{
    alert("Exception: " + ex);
}
*/

1 个答案:

答案 0 :(得分:1)

我认为您正在将普通套接字与WebSockets混淆。看着the documentation,看来您不应该使用IoServer,而应该使用WsServer。第一种似乎实现了普通套接字,而第二种似乎实现了您尝试从Javascript访问的WebSockets协议。