How to disconnect invalid clients immediately on Ratchet PHP? - php

I started learning Ratchet PHP. I did the first tutorial on Ratchet website (http://socketo.me/docs/hello-world) which basically just opens a server and sends incoming text messages to other clients.
I send messages with javascript console in Firefox and It works as expexted.
Meanwhile, without any specific reason I connect to Ratchet server with telnet localhost 8080. For sure it does nothing as the server expects WS protocol.
At this point, it is obivous that telnet is an invalid client for my app. So I don't want it to hang around and user my server's resources.
What can I do for this purpose? Is there an option or parameter I can specify to disconnect this connection or can I detect it easily with serverside code and disconnect it from there with some kind of fingerprint/agent or with a timeout?
Server code:
<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;
require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();

Related

how to make client connect to ratchet on live server?

I've googled about this for so many days and till now the client (browsers) cannot connect to the server.
But the server can run. I think its because its connected to itself(localhost).
I did find ratchet documentation which says:
If you want to open Ratchet up (not behind a proxy) set the third
parameter of App to '0.0.0.0'.
http://socketo.me/docs/troubleshooting
so i tried this in my server.php file. (doesn't work)
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8180,
'0.0.0.0'
);
Next i tried changing the app.php file which located here(doesn't work):
/vendor/cboden/ratchet/src/Ratchet/App.php
public function __construct($httpHost = '0.0.0.0', $port = 8180, $address = '0.0.0.0', LoopInterface $loop = null) {......
Then,i tried changing the port to something else. again the server can run but the client cannot connect.
I referred all these:
How to run Ratchet remotely or on a server?
How to run Ratchet remotely or on a server?
https://github.com/ratchetphp/Ratchet/issues/394
Someone please help. All I want is for the client to be able to connect to the ratchet websocket which is running on the server.

Can a Ratchet/ReactPHP loop listen to more than one port?

I've set up ReactPHP as a WebSocket listener so I can send out near-realtime updates to subscribed browsers. It looks like this:
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Listener;
$rootPath = realpath(__DIR__ . '/..');
require_once $rootPath . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Listener()
)
),
8081
);
$server->run();
All of those classes except for Listener are part of Ratchet, and the Listener is my handler implementation of \Ratchet\MessageComponentInterface, which responds to the open/close/error events of connecting WebSockets.
I would like this script to be contactable by a queue system I am building, and since that is a system channel, I would like to expose this on a different port so that it is not reachable from the internet. This would ideally be on HTTP rather than WebSocket; I have successfully used a PHP WebSocket client to contact this listener, but that's a bit complicated compared to a file_get_contents('http://...') call!
At a guess, the internal loop of React (e.g. StreamSelectLoop::streamSelect) only blocks for short time (see here) so it feels possible that it could manage a number of separate streams internally. Ideally, I would like the additional port to be handled by a separate listener, for security isolation (in case it is possible for a flaw in Guzzle to allow an attacker to appear to come from the restricted port when in fact they came from the internet port).
I think this is not an unusual requirement, but there does not seem to be any related information in the docs, and the GitHub issues are rather bare here too. Is this configuration possible without setting up parallel processes or multithreading?
One solution to this problem is to add IP whitelisting in the WebSocket listener for specific message types. I may do that in the short term, but listening on another port would be much nicer solution.
I found one way, it may be not a best practice, but you can manually add socket, like this:
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Listener;
use React\Socket\Server as Reactor;
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Listener()
)
),
8081 //Port 1
);
$socket = new Reactor($server->loop);
$socket->listen(8082, '0.0.0.0'); //Port 2
$socket->on('connection', [$server, 'handleConnect']);
$server->run();

PHP Ratchet can't connect from other device

I'm starting using PhP Ratchet socket. Following the guides I could made a simple chat application and it's working within the same computer. Example, if I open up chrome and firefox, I can interact send and receive messages, ok.
The problem is when I try to use the chat app from another computer, but within the same internet connection, or even when I tried to test it online.
When on lan, the other computers can't connect with the socket and online no one can connect.
By looking around, I found about using '0.0.0.0' or even port 5555 to enable connections from anyone. But even when using this, I can't connect.
How can I solve this? This is my files:
server.php
<?php
use Ratchet\Server\IoServer;
use Ratchet\http\HttpServer;
use Ratchet\WebSocket\WsServer;
require __DIR__ . '/../vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
), 2000, '0.0.0.0'
);
$server->run();
?>
And client js file:
var socket = new WebSocket('ws://127.0.0.1:2000');
127.0.0.1 will always point to the local device, which, on devices other than the socket server, will not point to the device that is hosting the socket server. If the device that is running the socket server is not routeable from the internet, you will not be able to connect to the socket from the internet.
You can test from other devices on your LAN by figuring out what your network IP is for the device that is running the server. Then in your client code, connect to that IP. It will probably be something close to 192.168.x.x, e.g. 192.168.1.12 (it could also be in the 10.x.x.x or 172.16.x.x address spaces). Then simply use that address to connect from your client script for testing:
var socket = new WebSocket('ws://192.168.1.12:2000');
You may still run into trouble if, for whatever reason, your network is configured to drop packets on port 2000. If so, it should be fairly easy for you to change to a different port for both your server and client.

How to run Ratchet remotely or on a server?

Everything works fine on my local machine on XAMPP. But after I uploaded the files to a server, it gives a error like this...
Fatal error: Uncaught exception 'React\Socket\ConnectionException' with message 'Could not bind to tcp://0.0.0.0:8080: Address already in use' in
/home/sites/jemaottest.com/public_html/websocket/vendor/react/socket/src/Server.php:29 Stack trace: #0
/home/sites/jemaottest.com/public_html/websocket/vendor/cboden/ratchet/src/Ratchet/Server/IoServer.php(70): React\Socket\Server->listen(8080, '0.0.0.0') #1
/home/sites/jemaottest.com/public_html/websocket/bin/chat-server.php(17): Ratchet\Server\IoServer::factory(Object(Ratchet\Http\HttpServer), 8080, '0.0.0.0') #2 {main} thrown in
/home/sites/jemaottest.com/public_html/websocket/vendor/react/socket/src/Server.php on line 29
when I run the chat-server.php file.
I found out something on the troubleshooting page of Ratchet which says,
If you want to open Ratchet up (not behind a proxy) set the third parameter of App to '0.0.0.0'.
I tried that but it didn't work,
<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;
require dirname(__DIR__).'/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080,
'0.0.0.0'
);
$server->run();
?>
it still gave the same error.
What should I do now?
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8282
);
Just Change the port and try.. mine is works fine after changing my port. And also don't forget to change the port in your port in websocket javascript class too.
var conn = new WebSocket('ws://yourdomain.com:8282');
I later found out using other ports are not allowed on a shared server.
If you are on a private server with a ssh access, you can try MarshallOfSound's solution.
Or if you just need the websocket as a service you can use something like Pusher.
It means that nother process is running on port 8080. Probably a webserver of some kind.
You can find out what is running with the command
lsof -i :8000
You can either stop the process already using the port. Or run Ratchet on a different port.

Always `Could not bind to tcp://my_ip_here:8080 Address already in use`

I was trying to deploy my websocket server and start running it but always gives:
PHP Fatal error:
Uncaught exception 'React\Socket\ConnectionException'
with message 'Could not bind to tcp://my_ip_here:8080:
Address already in use'
in /var/www/html/webscoket/vendor/react/socket/src/Server.php:29
here's my server.php:
<?php
require dirname(__DIR__) . '/vendor/autoload.php';
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\Socket\Server;
use React\ZMQ\Context;
$loop = React\EventLoop\Factory::create();
$app = new onyxsocket();
$webSock = new Server($loop);
$webSock->listen(8080, 'my_ip_here');
$webServer = new IoServer(
new HttpServer(
new WsServer(
$app
)
),
$webSock
);
$context = new Context($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://my_ip_here:5555');
$pull->on('error', function ($e) {
var_dump($e->getMessage());
});
$pull->on('message', array($app, 'onbroadcast'));
$loop->run();
What I've tried so far is to check available ports that can be used in the production server: netstat - anp gave me idea that port 8080 is free. But the problem is it still show the error Address already in use. I also tried other ports given by the administrator but no luck.
The server.php that I'm trying to deploy is working fine on localhost. But I don't know what do I need to do to make it work on a production server.
Need help. Thanks.
from #user3666197 comment above:
Clarify the code, pls. Your server-code ZeroMQ .bind() -s to port# 5555. So whose code binds to localhost port# 8080, that is reported in an unhandled exception above? How do you clean for a gracefull-exit any crashed EventLoop/Factory to release resources and avoid hanging orphans?
I decided to recheck the netstat: netstat -tulpen and check for the ports 8080 and 5555 and find out that there is registered PID on the port currently connecting. These application was also the same script that I want to run on console, server.php.
I kill the PID: kill PID_number and run the server.php on console again. It worked.

Categories