Websocket not send message until client is disconnected - javascript

I'm learning WebSocket using PHP library Ratchet. But I have a problem sending the message from client/browser. I have tried using chrome and firefox.
The message is not sent to the server until I disconnect the client by closing the tab or refresh the browser.
Update: My server use Centos 7 with firewalld enabled.
After I close the browser tab, the server output is like this:
Connection 73 sending message "tes" to 1 other connection
Connection 73 has disconnected
Here is the javascript code:
conn = new WebSocket('ws://websocket.develop.local:8080');
conn.onopen = function(e) {
console.log("Connection established!");
};
conn.onmessage = function(e) {
console.log('ada message');
console.log(e.data);
};
conn.onerror = function(e) {
console.log("WebSocket Error: " , e);
//Custom function for handling errors
//handleErrors(e);
};
function sendMessage(){
var message = document.getElementById("pesan").value;
conn.send(message);
console.log('Sending message: ' + message);
};
And here is the PHP code (I got this from Ratchet docs):
<?php
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) {
// 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();
}
}

Related

WebSocket Server https

I'm new with websocket things. I tried to make a simple chat application, and i've followed ratchet hello world tutorial. I ran it locally with
'ws://localhost:8080'
It's works perfectly fine. I can chat via javascript console like the tutorials said. Now, i try to put it on my webserver https://some.domain.co/websocket. I've tried to do the same thing like
'ws://some.domain.co:8080'
'ws://some.domain.co:8080/websocket'
'ws://some.domain.co/websocket:8080'
'wss://some.domain.co:8080'
'wss://some.domain.co:8080/websocket'
'wss://some.domain.co/websocket:8080'
But none of them work. By browser still give error
WebSocket connection to 'wss://some.domain.co/' failed: Error during
WebSocket handshake: Unexpected response code: 200
or
WebSocket connection to 'wss://some.domain.co:8080/' failed: Error in connection establishment: net::ERR_TIMED_OUT
I think i had something wrong with my url. Any advice? Thanks before
Edit
chatServer.php
require dirname(__DIR__) . '/vendor/autoload.php';
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
include("Chat.php");
require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
), 8080
);
$server->run();
Chat.php
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
echo "Server is Running\n";
}
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) {
$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();
}
}

Why my WebSocket Client always reload after sending a message?

I'm trying to make a chat using WebSocket. In that purpose I use Ratchet.
For that, I'm using the guide from Ratchet :
http://socketo.me/docs/hello-world
My problem is that after sending a message, the page reloads without any implementation of code for it.
index.html :
<html> <!-- index.html -->
<head>
</head>
<body>
<h1>Menu</h1>
<h2>Create a chat server on port 8080</h2>
<button>Here</button>
<hr>
<h2>Join the chat server on port 8080</h2>
<button>Here</button>
<p>You'll have an error if it doesn't exist !</p>
</body>
</html>
connection.js:
var conn;
function init(){
console.log("function : init");
conn = new WebSocket('ws://localhost:8080');
console.log(conn);
conn.onopen = function(e) {
var co = document.getElementById("connection");
co.innerHTML="Connection established !";
};
conn.onmessage = function(e) {
var content = document.getElementById("chat");
content.innerHTML = content.innerHTML + "<li>"+ e.data+"</li>";
};
conn.onclose = function(){
var co = document.getElementById("connection");
co.innerHTML="Connection closed !";
}
conn.onerror = function(){
alert("Connection failed : There in no server on this port !");
}
}
function closeCon(){
conn.close();
}
function sendMessage(){
var mes = document.getElementById("message").value;
conn.send(mes, function(event){
event.preventDefault();
console.log(event);
} );
}
chat-client.php :
<html><!-- chat-client.php -->
<head>
<script src="../js/connection.js"></script>
</head>
<body onload="init()">
<h1>Chat in web browser</h1>
<p id="connection"> Connection closed !</p>
<div>
<ul id="chat">
</ul>
<form>
<input id="message" style="border: 1;">
<button onclick="sendMessage()">Send</button>
</form>
</div>
<hr>
<button onclick="closeCon()">Back to the menu</button>
</body>
</html>
chat-server.php :
<h1>Welcome on your server on port 8080</h1>
<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;
// cd /Applications/MAMP/htdocs/MyRatchetFirstApp/
require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();
Chat.php :
<?php //Chat.php
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) {
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})<br/>";
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
foreach ($this->clients as $client) {
if ($from !== $client) {
// The sender is not the receiver, send to each client connected
$client->send($msg);
}
}
echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "<br/>", $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
}
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<br/>";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}<br/>";
$conn->close();
}
}
composer.json :
{
"autoload": {
"psr-0": {
"MyApp": "src"
}
},
"require": {
"cboden/ratchet": "0.3.*"
}
}
And finally, here,the tree of this project
That was just the button to send the message was in a form. Then when I "submit" it, it refreshed the page. If you want to have an history of the posts, you should remove this form.

PHP stream websockets

Im kinda new with the sockets stuff and Im trying to make a server on PHP to support websockets calls from my javascript currently my code looks like this
<?php
class Websocket
{
private $server;
private $sockets = [];
public function create($host)
{
$this->server = stream_socket_server('tcp://localhost:8080', $errno, $errmsg);
stream_set_blocking($this->server, 0);
}
public function run()
{
while(true)
{
$client = stream_socket_accept($this->server);
if($client)
{
$data = stream_socket_recvfrom($client, 2048);
if($data)
{
echo 'Client connected'.PHP_EOL;
echo $data;
$response = $this->handshake($data);
stream_socket_sendto($client, $response);
}
}
}
}
private function handshake($data)
{
$data = explode(PHP_EOL, $data);
foreach($data as $header)
{
$current_header = explode(':', $header);
if($current_header[0] == 'Sec-WebSocket-Key')
{
$accept = base64_encode(sha1(trim($current_header[1]).'258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
$response = 'HTTP/1.1 101 Switching Protocols'.PHP_EOL.'Upgrade: websocket'.PHP_EOL.'Connection: Upgrade'.PHP_EOL.'Sec-WebSocket-Accept:'.$accept.PHP_EOL.PHP_EOL;
return $response;
}
}
}
}
And my javascript is just a simple
var socket = new WebSocket('ws://localhost:8080');
socket.onopen = function(event)
{
console.log('connected');
socket.send('hello');
}
Currently the message connected appears on my chrome console but after that when the hello message is supposed to be sent I get this error
"connection to: xxx was interrupted while the page was loading"
So my question is after I have successfully send the handshake to the client how do I process messages? I know my code is always sending the handshake to new connections but on my server I will only see the first message beeing echoed (the http request) and not the "hello" one
You need to handle the message -
socket.onmessage = function(e){
var server_message = e.data;
console.log(server_message);
}

Have a PHP server script persistently listen on a socket non blocking?

I am writing a project that is in 2 parts.
So far I have a front end View.php (HTML5,CSS3,JQuery) and this will query the server.php
The server PHP opens a TCP socket to a server and listens in and can make commands by writing to the socket.
The normal procedure now goes like this
View.php -> Calls using rest API to server.php
Server.php -> Connects to TCP -> Reads from TCP -> Json_encodes & print -> close TCP socket connection.
What I want to achieve is a script Server.php that once started. It constantly listens in to a server, until it gets a shutdown command. I want to keep a fsocket connection open. Any thoughts?
The answer is using non blocking programming. In PHP we have specific function for non blocking I/O. For sockets you should use socket_set_nonblock function on a socket resource.
$port = 8081;
$address = '127.0.0.1';
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
exit();
}
if (socket_bind($sock, $address, $port) === false) {
echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
exit();
}
if (socket_listen($sock, 5) === false) {
echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}
socket_set_nonblock($sock);
echo "listening for new connection".PHP_EOL;
$conneted_clients = [];
do {
$clientsock = socket_accept($sock);
if($clientsock !== false){
socket_set_nonblock($clientsock);
$conneted_clients[] = $clientsock;
socket_getpeername($clientsock,$address);
echo "New Connection from: ".$address.PHP_EOL;
$msg = PHP_EOL."Welcome to the PHP Test Server. " . PHP_EOL.
"To quit, type 'quit'. To shut down the server type 'shutdown'." . PHP_EOL;
socket_write($clientsock, $msg, strlen($msg));
}
$status = check_clients($conneted_clients);
if(!$status) break;
usleep(500000);
} while (true);
function check_clients($clients)
{
foreach($clients as $key => $con)
{
if(get_resource_type($con) !== "Socket")
{
socket_getpeername($clientsock,$address);
echo $address." has diconnected.".PHP_EOL;
unset($clients[$key]);
continue;
}
if (false === $buff = socket_read($con, 2048)) {
continue;
}
$buff = trim($buff);
if ($buff == 'quit') {
socket_close($con);
unset($clients[$key]);
continue;
}
if (trim($buff) == 'shutdown') {
socket_close($con);
echo "shutdown initiated".PHP_EOL;
return FALSE;
}
if($buff != false || $buff != null)
{
$talkback = "PHP: You said '$buff'.".PHP_EOL;
socket_write($con, $talkback, strlen($talkback));
echo "$buff".PHP_EOL;
}
}
return TRUE;
}
echo "Closing Server";
socket_close($sock);

WebSocket Events Not Firing

I'm trying to create a simple WebSocket example using the HTML5/JS API. Based on what I trace out on the server, it seems like the socket is connecting, but none of the events fire (onopen, onmessage, onclose, etc). I'm a Flash developer so I'm not very good at debugging the JavaScript and I'm hoping someone can help me out. Here's the client side code I'm using:
<script type="text/javascript" charset="utf-8">
function startSocket()
{
if("WebSocket" in window)
{
var ws = new WebSocket("ws://localhost:1740");
ws.onopen = function() {
window.alert("open!");
}
ws.onmessage = function(event) {
window.alert(event.data);
}
ws.onclose = function() {
window.alert("Closed");
}
ws.onerror = function() {
window.alert("trouble in paradise");
}
}
}
</script>
And here's my socket server code (which works just fine from Flash, but that may not mean anything):
<?php
create_connection('localhost',1740);
function create_connection($host,$port)
{
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
if (!is_resource($socket)) {
echo 'Unable to create socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
} else {
echo "Socket created.\n";
}
if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
} else {
echo "Set options on socket.\n";
}
if (!socket_bind($socket, $host, $port)) {
echo 'Unable to bind socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
} else {
echo "Socket bound to port $port.\n";
}
if (!socket_listen($socket,SOMAXCONN)) {
echo 'Unable to listen on socket: ' . socket_strerror(socket_last_error());
} else {
echo "Listening on the socket.\n";
}
while (true)
{
$connection = #socket_accept($socket);
if($connection)
{
echo "Client $connection connected!\n";
send_data($connection);
} else {
echo "Bad connection.";
}
}
}
function send_data($connection)
{
echo $connection;
// Create a number between 30 and 32 that will be our initial stock price.
$stock_price = rand(30,32);
while (true)
{
socket_write($connection,"$stock_price\n",strlen("$stock_price\n"));
sleep(1);
// Generate a random number that will represent how much our stock price
// will change and then make that number a decimal and attach it to the
// previous price.
$stock_offset = rand(-50,50);
$stock_price = $stock_price + ($stock_offset/100);
echo "$stock_price\n";
}
}
?>
Are you calling startSocket() somewhere else in your code?
I know this code works. You might be able to adapt it: http://github.com/dshaw/zombo-socket/blob/master/zombocom-client.html
Maybe this is completely obvious, but if anyone else gets this, the problem is that you need to add a handshake. In Flash this isn't required and I still don't fully understand it, but I was able to modify this project - http://code.google.com/p/phpwebsocket/ - and it worked as it was supposed to by adding the gethandshake code after my socket_accept code ran.

Categories

Resources