I made a Websocket server using ratchet and php it works fine but the problem is it's not multi thread and this makes the server replay late when multiple clients send messages to the server at the same time.
I want to know if there is any way to make it multi thread so each connection run on it's own thread or if it's not the right way give me a better one
Thanks!
Chat.php codes:
<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
require 'vendor/autoload.php';
require(dirname(dirname(__FILE__)).'/inc/class/class-app_api.php');
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
echo 'server Started!';
}
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');
$obj = new \app_api($from, $msg);
$res = $obj->handleRequest();
if (is_array($res)) {
foreach ($this->clients as $client) {
if ($from != $client) {
// The sender is not the receiver, send to each client connected
$client->send($res['data']);
}
}
}else {
$from->send($res);
}
}
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";
$obj = new \venicehost_app_api($from);
$conn->send($obj->setError('An error has occurred:' . $e->getMessage()));
//$conn->close();
}
}
?>
Server.php codes:
<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;
require_once("Chat.php");
//require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
port,
ip address
);
$server->run();
?>
Related
i am using php ratchet websockets on my shared server on one domain the ratchet websockets is working perfectly but when i run sockets on my other domain it give me some tcp errors both of my domains are on the same server.
That is my socket.php code many time I changes my port number also but nothing happended
<?php
require __DIR__ . '/vendor/autoload.php';
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
require 'chat.php';
$loop = React\EventLoop\Factory::create();
// Run the server application through the WebSocket protocol on port 8888
$app = new Ratchet\App("example.com", 8888, '0.0.0.0',$loop);
$app->route('/chat', new Chat, array('*'));
$app->run();
$app->enableKeepAlive($app->loop, 10);
?>
and here is my chat.php code
<?php
require __DIR__ . '/vendor/autoload.php';
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = array();
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients[$conn->resourceId] = $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 $key => $client) {
if ($from !== $client) {
// The sender is not the receiver, send to each client connected
$client->send($msg);
}
}
// Send a message to a known resourceId (in this example the sender)
$client = $this->clients[$from->resourceId];
$client->send("Message sent to $numRecv users.");
}
public function onClose(ConnectionInterface $conn) {
// The connection is closed, remove it, as we can no longer send it messages
unset($this->clients[$conn->resourceId]);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}
?>
now when i run php socket.php on command line than it is not doing anything and when i run the socket.php url it shows this page isn't workingbelow is my composer.json code
{
"require": {
"cboden/ratchet": "^0.4.2",
"textalk/websocket": "^1.3"
}
}
I also installed mbstring and iconv in my domain.
The error is:
PHP Fatal error: Uncaught RuntimeException: Failed to listen on
"tcp://127.0.0.1:8843": Address already in use in
/home/example.com/public_html/test/rachet/vendor/react/socket/src/TcpServer.php:164
I am creating a ratchet chat application. It is currently on my localhost 8080 however I want to connect it to my google app engine project what can I do
Here is my Ratchet code:
class Chat 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 . " Hello ");
}
}
}
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();
}
}
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();
Does App Engine support that, if not what other alternatives can I use to deploy my chat on a live application
I am trying to implement Ratchet Socket Hello word on my local machine every things works perfectly but on vps centos server when i run server service with
ssh Command : php chat-server.php
it start Listening on port correctly(i can see on linux that port is Listening ) , but when i open "clint.html" page the method onopen never fire but server says
new client connected !
and after 2 minute it says
client disconnected
if i send message to client it will take 2 minutes then client will receive it, but it will disconnect again
it seems to me that there is not stable connection between server and client. every time when i check websocket.readyState its not equal to 1
i disabled firewall and any security on vps server but still have this problem.
i have to mention that normal php socket functions works without problem because i could test it and every thing works
but about ratchet it seems it hang on onopen method.
port 9091 is open
firewall is disabled
abrandao.com/2013/06/websockets-html5-php/ works whiteout problem and can send and receive message from clients
BUT Ratchet has problem onconnect
chat-server.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()
)
),
9091
);
echo date("Y-m-d H:i:s")." chat-server Started on port 9091 \n";
$server->run();
Chat.php class :
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo date("Y-m-d H:i:s")." New connection! ({$conn->resourceId})\n";
$conn->send("Hello {$conn->resourceId} from server at : ".date("Y-m-d H:i:s"));
echo date("Y-m-d H:i:s")." Hello Sent to ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
echo sprintf(date("Y-m-d H:i:s").'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) {
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo date("Y-m-d H:i:s")." Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo date("Y-m-d H:i:s")." An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}
client html :
$(document).ready(function(){
connect();
});
var wsUri = "ws://myserverdomain.comOrIP:9091";
function connect() {
var ws = new WebSocket(wsUri);
ws.onopen = function() {
var now = new Date();
console.log(now + ' Connected to '+wsUri);
};
ws.onmessage = function(e) {
var now = new Date();
console.log(now + ' Message Recived From Server :', e.data);
};
ws.onclose = function(e) {
var now = new Date();
console.log(now +' Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
setTimeout(function() {
connect();
}, 1000)
};
ws.onerror = function(err) {
var now = new Date();
console.error(now + ' Socket encountered error: ', err.message, 'Closing socket')
console.error(err)
ws.close()
};
}
I have a PHP based Websocket server that is used to connect web clients. The WebSocket server itself serving as a Client for WhatsApp. I want when server goes up, it then make a call to WhatsApp and make a live connection. Below is my WebSocket Class. Since there's an infinite While loop, other things are not being called; like connecting a client.
How do I make it that when Web Socket server loads up, it makes a connection to WhatsApp server as well and then let other clients to connect Web Socket server
Chat.php
#!/usr/local/bin/php
<?php
ini_set('display_errors',1);
error_reporting(E_ALL);
require_once __DIR__.'/vendor/autoload.php';
require_once 'vendor/whatsapp/chat-api/src/whatsprot.class.php';
require_once 'vendor/whatsapp/chat-api/src/events/MyEvents.php';
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Guzzle\Http\Client;
use Guzzle\Http\EntityBody;
use Guzzle\Http\Message\Request;
use Guzzle\Http\Message\Response;
class Chat implements MessageComponentInterface {
protected $clients;
protected $message;
protected $client_info = []; //To hold which agent was connected
protected $username = 'xx';
protected $password = 'xx=';
protected $nickname = 'xx Number';
protected $target = "xx";
protected $debug = false;
public function __construct() {
$this->clients = new \SplObjectStorage;
print("..Server is coming up..\n");
echo "[] Logging in as '$this->nickname' ($this->username)\n";
$w = new WhatsProt($this->username, $this->nickname, $this->debug,true,__DIR__.'/wadata/');
$events = new MyEvents($w);
$events->setEventsToListenFor($events->activeEvents);
$w->connect();
$w->loginWithPassword($this->password);
print("..Accepting WhatsApp Messages...\n");
while (1) {
$w->pollMessage();
}
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients->attach($conn);
//Identity Message
$this->message = json_encode(['STATUS'=> 'CONNECTED','CLIENT_ID' => $conn->resourceId]);
$conn->send($this->message);
$this->message = json_encode(['STATUS' => 'NEW', 'TYPE'=> 'TEXT','MESSAGE' => "This is by customer"]);
//Actual WhatsApp message
$conn->send($this->message);
echo "New connection! ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
print("CLIENT SAYS:- ".$msg."\n");
foreach ($this->clients as $client) {
if ($from === $client) {
$msg = 'WA Server responds:- '.$msg;
$client->send($this->message);
}
}
}
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();
}
}
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();
I managed to create a web service that listens on port 80 for http requests and handles ajax calls and also long polling.
But I'm stuck at creating a similar websocke server in the same php file
<?php
require_once('vendor/autoload.php');
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat 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);
$conn->send('aa');
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();
}
}
$loop = React\EventLoop\Factory::create();
$swsa=new Chat;
$webSock = new React\Socket\Server($loop);
$webSock->listen(8687, '127.0.0.1'); // Binding to 0.0.0.0 means remotes can connect
$webServer = new Ratchet\Server\IoServer(
new Ratchet\Http\HttpServer(
new Ratchet\WebSocket\WsServer(
$swsa
)
),
$webSock
);
$app = function ($request, $response) {
//some code here to manage requests
$response->writeHead(200,array('Content-Type'=>'application/json'));
$response->end(json_encode(array('ok'=>'ok')));
};
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket, $loop);
$http->on('request', $app);
$socket->listen(8485);
$loop->run();
Code in browser:
var wsUri = "ws://127.0.0.1:8687/";
websocket = new WebSocket(wsUri);
This triggers an error in the browser
Firefox can't establish a connection to the server at ws://127.0.0.1:8687/
Your IoServer initialization is incorrect. If you check the code for IoServer class, you will find:
public function __construct(MessageComponentInterface $app,ServerInterface $socket, LoopInterface $loop = null)
and
public function run() {
if (null === $this->loop) {
throw new \RuntimeException("A React Loop was not provided during instantiation");
}
// #codeCoverageIgnoreStart
$this->loop->run();
// #codeCoverageIgnoreEnd
}
The IoServer class object has no loop assigned to it and hence it fails to execute. Try passing loop as your third argument.