Wie Verbinde ich zu einem raw-TCP-socket-server aus web-app?

Ich habe eine web-gehostete Anwendung auf AWS-geschrieben in Laravel/PHP, ich muss lassen Sie die web-Anwendung zu sprechen, mit einem socket-server lauscht auf port 9090 in einen server in einem internen Netzwerk (nicht im AWS), der Browser, die Nutzung der webapp; der socket-server muss NICHT Unterstützung der websocket-aber nur raw-sockets; wie kann der client eine Verbindung zum socket-server? Brauche ich zu schreiben client-Programme, die in python/andere lang-Installation auf client-Rechnern oder gibt es eine bessere Möglichkeit?

  • nodejs könnte eine option für Sie
  • Sie können schreiben, ein paar kleine proxy-Server: (1) eine Verbindung zu den raw-socket und relais-Nachrichten an die (2) zweite websocket-server, dass die clients eine Verbindung herstellen. Schauen Sie in Ratschet docs.
  • Wie funktioniert der socket-server arbeiten? Ist es bidirektional request/response? Oder unidirektional; server-Ereignisse ausgibt und die Kunden nur hören oder clients Daten senden und der server speichert/verarbeitet die Daten?
  • server-gets-Befehl und gibt ein OK/KO “ als Antwort; der server Autor sagte mir, es ist ein raw-socket-server, der keine websocket-Unterstützung, so bin ich das denken, wie Sie zu verbrauchen
  • Do i need to write client programs or is there a better way? – schreiben Sie einen proxy-server wie ein erwähnt im 1. Kommentar. Eine Lösung habe ich für etwas ähnliches geschrieben mit ReactPHP und Ratsche. Ich bin am überlegen, wie es zu eigen, was Sie brauchen.
InformationsquelleAutor Cris | 2017-10-25



3 Replies
  1. 2

    Ja, Sie schreiben zu müssen-client-Programm/script, das hören würde, an die Steckdose und verwenden Sie das Skript, die Sie Bearbeiten können front-end-Seiten.

    Ich würde empfehlen, Javascript-code, der es hören wollte, um Ihre web-socket bei 9090 und basierend auf den erhaltenen Daten, können Sie änderungen auf der web-Seite.

    Hier ist der Beispiel-code für Ihre Referenz.

    <script src="http://localhost:8080/socket.io/socket.io.js"></script>
    <script>
        //Create SocketIO instance, connect
    
        var socket = new io.Socket();
    
        socket.connect('http://127.0.0.1:8080'); 
    
        //Add a connect listener
        socket.on('connect',function() {
          console.log('Client has connected to the server!');
        });
        //Add a connect listener
        socket.on('message',function(data) {
          console.log('Received a message from the server!',data);
          //This `data` can be used to show on the page or anything else.
        });
        //Add a disconnect listener
        socket.on('disconnect',function() {
          console.log('The client has disconnected!');
        });
    
        //Sends a message to the server via sockets
        function sendMessageToServer(message) {
          socket.send(message);
        };
    </script>
    • Danke, aber wenn ich habe gut verstanden-Buchse.io nutzt websocket nicht unterstützt wird, wird in der socket-ich bin versucht zu verbinden.
    • Wie hast du erkennen, dass es nicht unterstützt wird?
    • Ich habe gefragt, den Autor des socket-server, der sagte, dass es nicht die Unterstützung der websocket-aber nur raw-sockets.
    • Dies ist der raw-socket. Probieren Sie es aus. Ich bin sicher, dass dies funktionieren würde.
    • versuchen Sie, und sagen Sie mir, wenn Sie irgendwelche Probleme.
    • Browser nicht unterstützt raw-TCP-sockets. Browser unterstützen nur HTTP und WebSockets. WebSockets müssen spezielle Initialisierung mithilfe des upgrade-Anfrage (Upgrade: websocket) und Sie haben auch Ihre eigene Paket-framing. Sie sicher, dass HTTP und WebSockets verwenden Sie raw-sockets unter, aber jedes Protokoll auf der Internet-Sie auch nutzen.
    • wie haben Sie die Lösung finden?

  2. 1

    Also werden wir die Kiste ein paar von Prozessen; (1) eine WebSocket-server, die browser-clients eine Verbindung herstellen, (2) einem raw-socket-client die Verbindung mit dem raw-socket-server. Diese 2 Prozesse tauschen Nachrichten mithilfe von Null-Messaging-Queue.

    Müssen Sie php-cli, php-zmq, libevent (optional, aber dringend empfohlen) und libevent in PHP-wrapper auf Ihrem system installiert. Sie müssen die Ratsche (cboden/ratchet), react/zmq, react/promise
    (und vielleicht noch etwas, das ich vergessen) installiert, mit Komponist. Ich empfehle Ihnen, erstellen Sie eine Proxy Verzeichnis in Laravel ist app/ – Verzeichnis. Also die namespace ist app\Proxy nach dem PSR-4.

    ReactPHP verwendet event-Schleifen zu emulieren user-space-threading (so ziemlich das gleiche wie V8 node.js es tut), so werden Sie sehen, eine Menge von Schleifen im code.

    Haftungsausschluss:

    Habe ich nicht getestet, dieser code. Es kann einige debugging. Aber es wird Ihnen eine gute Idee, was Sie tun sollten. Wenn Sie Fehler finden, fühlen Sie sich frei, zu kommentieren oder einfach nur Bearbeiten und korrigieren Sie den code. Update: getestet habe ich es mit PHP-test-server und es funktioniert wie erwartet.

    websocket_server_bootstrapper.php

    <?php
    namespace app\Proxy;
    require dirname ( dirname ( __DIR__ ) ) . '/vendor/autoload.php';
    require 'WebsocketServer.php';
    
    //create an event loop
    $loop = \React\EventLoop\Factory::create ();
    //pass it to React's wrapper class of PHP's ZMQContext native class
    $context = new \React\ZMQ\Context ($loop);
    
    //create an instance of the WebsocketServer class, the code for it is below
    $pusher = new WebsocketServer($loop, $context);
    
    //create a ZMQ pull socket which the WebsocketServer class will use to 
    //get messages from the raw socket client (the code below)
    $pull = $context->getSocket ( \ZMQ::SOCKET_PULL );
    //bind it to inter-process communication on Linux shared memory
    $pull->bind ( 'ipc:///dev/shm/websock0' );
    //when you get a message from socket client run this method on WebsocketServer
    $pull->on ( 'message', [
      $pusher,
      'onExternalMessage'
    ]);
    
    //create a Ratchet app
    $server = new \Ratchet\App ( 'localhost', 8090, '0.0.0.0', $loop );
    //wrap our WebsocketServer class in Ratchet's WsServer
    $wrappedPusher = new \Ratchet\WebSocket\WsServer($pusher);
    //give it a route on your website (now it's root)
    $server->route ( '/', $wrappedPusher, array (
      '*'
    ) );
    //start event loop's infinite loop
    $loop->run ();

    Wenn Sie don verwenden möchten ipc für ZMQ-Nachrichten Sie können mit TCP usw. Lesen Sie mehr in der ZMQ Buch.

    WebsocketServer.php

    Zunächst, was diese Klasse tut, ist es akzeptiert WebSocket-verbindungen und stellt Sie in $clients (das ist ein\SplObjectStorage) und $cnToConnection (das ist ein array) von Eigenschaften von Klassen. $cnToConnection ist „- Anschluss Anzahl Anschluss“ assoziatives array, welches ich als einen index zu finden, eine Verbindung schnell. Ich benutze Verbindungsnummer zu übergeben es an die raw-socket-client also wenn der client eine Antwort bekommen von der raw-socket-server ich wissen, welche Verbindung ich sollte schicken Sie die Antwort.

    <?php
    namespace app\Proxy;
    use Ratchet\MessageComponentInterface;
    use Ratchet\ConnectionInterface;
    use React\EventLoop\LoopInterface;
    use React\ZMQ\Context;
    
    class WebsocketServer implements MessageComponentInterface{
        /**
         * @var \SplObjectStorage<CustomConnection,int> $clients these are
         * your clients connected from browsers
         */
        protected $clients;
    
        /**
         * @var ConnectionInterface[]
         */
        protected $cnToConnection;
    
        /**
         * @var \React\ZMQ\SocketWrapper
         */
        protected $rawSockPusher;
    
        /**
         * @var LoopInterface $loop
         */
        protected $loop;
    
        /**
         * @var int
         */
        protected $lastConnectionNumber = 0;
    
        public function __construct(LoopInterface $loop, Context $context)
        {
            $this->loop = $loop;
            $this->clients = new \SplObjectStorage;
    
            //create a push socket from the same ZMQ 
            //context we used in the bootstrapper
            $this->rawSockPusher = $context->getSocket(\ZMQ::SOCKET_PUSH);
            $this->rawSockPusher->connect('ipc:///dev/shm/raw_sock_proxy0');
        }
    
        public function onOpen(ConnectionInterface $conn)
        {
            //increment lastConnectionNumber from 0 up to 10M and then back to 0
            //I doubt you'll have more then 10M open connections :)
            $con_number = $this->lastConnectionNumber++ % 10000000;
            //$con_number is the key, $conn is the value
            $this->cnToConnection[$con_number] = $conn;
            //$conn is the key, $con_number is the value
            $this->clients->attach($conn, $con_number);
        }
    
    
        /**
         * Get message from browser client.
         * @param ConnectionInterface $from
         * @param string $msg
         */
        public function onMessage(ConnectionInterface $from, $msg)
        {
            //get connection number
            $cn = $this->clients->offsetGet($from);
            //put cn and the message in an array, serialize 
            //and send to the raw socket client
            $this->rawSockPusher->send(serialize(['cn' => $cn, 'data' => $msg]));
        }
    
        public function onClose(ConnectionInterface $conn)
        {
            //on closing the connection remove it from both collections
            $cn = $this->clients->offsetGet($conn);
            $this->clients->detach($conn);
            unset($this->cnToConnection[$cn]);
        }
    
        public function onError(ConnectionInterface $conn, \Exception $e)
        {
            //TODO: Implement onError() method.
        }
    
        public function onExternalMessage($message)
        {
            //get the response from the raw socket client
            $unserialized_mess = unserialize($message);
            //find the connection by connection number and send the response
            $this->cnToConnection[$unserialized_mess['cn']]
                ->send($unserialized_mess['data']);
        }
    }

    Hinweis: ich schrieb diesen code basierend auf Ratchet 0.3.6 die nicht-support-server auf den client pingen. Jetzt Ratsche 0.4 ist draußen und es unterstützt Ping. Sie müssen die ping-Kunden zu wissen, Sie sind immer noch da. Wenn der client nicht die Verbindung schließen, richtig du wirst tot verbindungen in Ihrem $clients und $cnToConnection Sammlungen. Lesen Sie über die Ping-Ratsche docs an http://socketo.me/.

    raw_socket_client_bootstrapper.php

    <?php
    namespace app\Proxy;
    require dirname ( dirname ( __DIR__ ) ) . '/vendor/autoload.php';
    require 'RawSocketClient.php';
    
    $loop = \React\EventLoop\Factory::create ();
    $context = new \React\ZMQ\Context ($loop);
    
    new RawSocketClient($loop, $context);
    
    $loop->run();

    Gibt es hier nichts neues im Vergleich zu websocket_server_bootstrapper.php

    RawSocketClient.php

    <?php
    namespace app\Proxy;
    
    use React\EventLoop\LoopInterface;
    use React\ZMQ\Context;
    use React\Socket\Connector;
    use React\Socket\ConnectionInterface;
    
    class RawSocketClient
    {
    
        /**
         * @var LoopInterface $loop
         */
        protected $loop;
    
        /**
         * @var Connector
         */
        protected $connector;
    
        /**
         * @var \ZMQSocket $websockPush
         */
        protected $websockPush;
    
        public function __construct(LoopInterface $loop, Context $context)
        {
            $this->loop = $loop;
    
            $pull = $context->getSocket(\ZMQ::SOCKET_PULL);
            $pull->bind('ipc:///dev/shm/raw_sock_proxy0');
            $pull->on('message', [
                $this,
                'onExternalMessage'
            ]);
    
            $this->connector = new Connector($this->loop, [
                'tcp' => true,
                'tls' => false,
                'unix' => false
            ]);
    
            $this->websockPush = $context->getSocket(\ZMQ::SOCKET_PUSH);
            $this->websockPush->connect('ipc:///dev/shm/websock0');
        }
    
        public function onExternalMessage($message)
        {
            //unserialize the message from the WebSocket server
            $unserialized_mess = unserialize($message);
    
            //connect to the raw socket server
            $this->connector->connect('tcp://raw_socket_server_address:port_number')
                 //connect() returns a promise
                ->then(function (ConnectionInterface $connection) use ($unserialized_mess) {
                    //when connected register a handler for the onData event
                    $connection->on('data', function ($data) use ($unserialized_mess, $connection) {
                        //receive the response and send it together with the connection number
                        $this->websockPush->send(serialize(['data' => $data, 'cn' => $unserialized_mess['cn']]));
                        $connection->close();
                    });
                    //send your message to the raw server
                    $connection->write($unserialized_mess['data']);
                }, function ($error) {
                    //TODO handle error
                });
        }
    }

    Hinweis: ich öffnen und schließen einer Verbindung auf jede Nachricht vom WebSocket-server. Kann Sie wiederverwenden können diese verbindungen durch die Schaffung $cnToConnection in dieser Klasse zu. Ich überlasse es Ihnen.

    Läuft das Ding

    Führen Sie diese Prozesse aber CLI. Einfach, indem Sie php websocket_server_bootstrapper.php und php raw_socket_client_bootstrapper.php. Sie können führen Sie Sie in beim start von /etc/rc.local oder durch so etwas wie Supervisord. Hinweis: Sie können führen Sie dann eine weitere Instanz von raw_socket_client_bootstrapper.php – ZMQ kümmern Lastenausgleich zwischen den Instanzen. Also, wenn Sie brauchen, um zu tun, einige Bearbeitung in der raw-socket-client.

  3. 0

    Vereinbart mit den oben genannten, oder Sie können einfach verwenden Sie ein vorhandenes Echtzeit-framework/server/Plattform abstrahiert die websockets Logik für Sie und lassen Sie Sie direkt plugin die sdk in Ihre bestehende Anwendung. Dies könnte mit Schieber, pubnub, deepstream, FB etc.

    Ich habe persönlich deepstream aus diesen. Es ist open Source und kommt einem selbst gehosteten node.js server.Es hat eine saubere Dokumentation, so dass Sie vielleicht wollen prüfen, ob aus.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.