Socket.io/ PHP server side - php

I use socket.io for socket app in my client side. For the server I use socket library of PHP.
After the handsake, the connection was closed and generated a warning
failed: WebSocket is closed before the connection is established.
socket_getsockname($socket_server, $addr, $port);
while($socket = socket_accept($socket_server)) {
$handshake = false;
if(!$socket){
print "error \n";
}
socket_getpeername($socket, $raddr, $rport);
$msg = "Welcome aboard !";
$length = strlen($msg);
print socket_read ( $socket , 255 )."\n";
$error = socket_last_error($socket);
$error_message = socket_strerror($error);
if(!$handshake){
$bytes = socket_recv($socket,$buffer,2048,0);
list($resource,$host,$origin,$key,$key1,$key2,$l8b) = getheaders($buffer);
$accept = base64_encode(SHA1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
$upgrade = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" .
"Upgrade: WebSocket\r\n" .
"Connection: Upgrade\r\n" .
"Sec-WebSocket-Origin: " . $origin . "\r\n" .
"Sec-WebSocket-Location: ws://" . $host . $resource . "\r\n" .
"Sec-WebSocket-Accept: " . $accept . "\r\n\r\n";
if(socket_write($socket,$upgrade.chr(0),strlen($upgrade.chr(0)))) {
$handshake = true;
}
}
else{
if(socket_write ( $socket , $msg,$length)){
print "Mesg envoyee \n";
}
}
do{
$read = socket_read($socket, 1080);
print $read."\n";
if(socket_write ( $socket , $msg,$length)){
print "Mesg envoyee \n";
}
} while ($read != '');
in my server side in PHP
in my client :
var socket = io('http://localhost:4454',{
agent: false,
transports: ['websocket']
});
console.log(socket);
socket.on('connect', () => {
socket.send('hi');
console.log(socket);
});
socket.emit('foo');
socket.on('message', (data) => {
console.log(data);
console.log(socket);
});
socket.on('data', (data) => {
console.log(data);
});
socket.on('error', (error) => {
console.log(error);
});
//blocage des reconnection si erreurs
var attemp = 5;
socket.on('reconnecting', (attemp) => {
console.log("I'm sad :(");
//socket.close();
});
I don't find any solution for this issue.
I don't understand why in localhost stream was automatically close.
Server side looked fine, in this time...

Related

Websocket handshake connection error in PHP

Error showing in console : WebSocket connection to
'ws://localhost/socket/php-socket.php/wss' failed: Error during
WebSocket handshake: Unexpected response code: 200
PHP Code :
$newSocket = socket_accept($socketResource);
$clientSocketArray[] = $newSocket;
$header = socket_read($newSocket, 1024);
$chatHandler->doHandshake($header, $newSocket, HOST_NAME, PORT);
enter code here
Handshake function :
function doHandshake($received_header,$client_socket_resource, $host_name, $port) {
$headers = array();
$lines = preg_split("/\r\n/", $received_header);
foreach($lines as $line)
{
$line = chop($line);
if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
{
$headers[$matches[1]] = $matches[2];
}
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$buffer = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host_name\r\n" .
"WebSocket-Location: ws://$host_name:$port/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_socket_resource,$buffer,strlen($buffer));
}
Javascript Code :
var websocket = new WebSocket("ws://localhost/socket/php-socket.php");
websocket.onopen = function(event) {
showMessage("<div class='chat-connection-ack'>Connection is established!</div>");
}

How can I send data/text from PHP using WebSocket to process?

I have process on server which acts as WebSocket server (not written in Ratchet). I want to be able to send data to this process using PHP (as client).
I found a lot of examples to send as TCP like this:
<?php
$addr = gethostbyname("localhost");
$client = stream_socket_client("tcp://$addr:8887", $errno, $errorMessage);
if ($client === false) {
throw new UnexpectedValueException("Failed to connect: $errorMessage");
}
fwrite($client, "GET / HTTP/1.0\r\nHost: localhost\r\nAccept: */*\r\n\r\n");
echo stream_get_contents($client);
?>
All I need I to send message to the process and close the connection. The result that I expect is the result from the webSocket will be later printed or "echo" to the PHP page.
Is there a way to make it work with curl in php?
I have found this code on github, (I can't find the exact repo where I got it from because I have looked and tried a lot of them)
<?php
class WebsocketClient {
private $_Socket = null;
public function __construct($host, $port) {
$this->_connect($host, $port);
}
public function __destruct() {
$this->_disconnect();
}
public function sendData($data) {
// send actual data:
fwrite($this->_Socket, "\x00" . $data . "\xff") or die('Error:' . $errno . ':' . $errstr);
$wsData = fread($this->_Socket, 2000);
$retData = trim($wsData, "\x00\xff");
return $retData;
}
private function _connect($host, $port) {
$key1 = $this->_generateRandomString(32);
$key2 = $this->_generateRandomString(32);
$key3 = $this->_generateRandomString(8, false, true);
$header = "GET /echo HTTP/1.1\r\n";
$header.= "Upgrade: WebSocket\r\n";
$header.= "Connection: Upgrade\r\n";
$header.= "Host: " . $host . ":" . $port . "\r\n";
$header.= "Origin: http://localhost\r\n";
$header.= "Sec-WebSocket-Key1: " . $key1 . "\r\n";
$header.= "Sec-WebSocket-Key2: " . $key2 . "\r\n";
$header.= "\r\n";
$header.= $key3;
$this->_Socket = fsockopen($host, $port, $errno, $errstr, 2);
fwrite($this->_Socket, $header) or die('Error: ' . $errno . ':' . $errstr);
$response = fread($this->_Socket, 2000);
/**
* #todo: check response here. Currently not implemented cause "2 key handshake" is already deprecated.
* See: http://en.wikipedia.org/wiki/WebSocket#WebSocket_Protocol_Handshake
*/
return true;
}
private function _disconnect() {
fclose($this->_Socket);
}
private function _generateRandomString($length = 10, $addSpaces = true, $addNumbers = true) {
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"ยง$%&/()=[]{}';
$useChars = array();
// select some random chars:
for ($i = 0; $i < $length; $i++) {
$useChars[] = $characters[mt_rand(0, strlen($characters) - 1)];
}
// add spaces and numbers:
if ($addSpaces === true) {
array_push($useChars, ' ', ' ', ' ', ' ', ' ', ' ');
}
if ($addNumbers === true) {
array_push($useChars, rand(0, 9), rand(0, 9), rand(0, 9));
}
shuffle($useChars);
$randomString = trim(implode('', $useChars));
$randomString = substr($randomString, 0, $length);
return $randomString;
}
}
$WebSocketClient = new WebsocketClient('localhost', 8887);
echo $WebSocketClient->sendData("MyUserNameFromPHP");
unset($WebSocketClient);
?>
Out of 7 php websocket clients that I tried, this is the only one that I was able to work with.
It doesn't requires any external files or frameworks.
This is simple implementation for executing short command that doesn't require persistent connection to webSocket server.
I hope it helps you guys , and you will save some time !!!

Connection between Node.JS and PHP via UNIX Socket - EPIPE write error

I'm trying to create a bridge between my application created in PHP and Node.JS.
Node.JS creates socket and listening to it, my code:
var net = require('net'),
fs = require('fs');
var path = '/tmp/echo.sock';
fs.unlink(path, function () {
var server = net.createServer(function(c) {
console.log('server connected');
c.on('close', function() {
console.log('server disconnected');
});
c.write('hello\r\n');
c.on('data', function(data) {
console.log('Response: "' + data + '"');
c.write('You said "' + data + '"');
});
});
server.listen(path, function(e) {
console.log('server bound on %s', path);
});
});
process.on('uncaughtException', function (err) {
console.log( "UNCAUGHT EXCEPTION " );
console.log( "[Inside 'uncaughtException' event] " + err.stack || err.message );
});
And my PHP code just connecting with exists socket and send some data:
$fp = fsockopen("unix:///tmp/echo.sock", -1, $errno, $errstr);
if (!$fp) {
return "ERROR: $errno - $errstr<br />\n";
} else {
fwrite($fp, "Hello World <3");
$out = fread($fp, 8192);
fclose($fp);
return $out; // That code is in function.
}
Everything should working, but in Node.JS console I see response:
server bound on /tmp/echo.sock
server connected
Response: "Hello World <3"
UNCAUGHT EXCEPTION
[Inside 'uncaughtException' event] Error: write EPIPE
at exports._errnoException (util.js:745:11)
at Object.afterWrite (net.js:763:14)
server disconnected
And in PHP I see just first message, hello. Why and how can I fix that?
try this;
<?php
$fp = fsockopen("unix:///tmp/echo.sock", -1, $errno, $errstr);
if (!$fp) {
return "ERROR: $errno - $errstr<br />\n";
} else {
$out = fread($fp, 8192);
fwrite($fp, "Hello World <3");
$out2 = fread($fp, 8192);
fclose($fp);
echo $out; // That code is in function.
echo $out2; // That code is in function.
}
?>
I know where's the problem. In PHP I close the connection to the pipe after write data. Node tries to write response but it can't, because connection in PHP is already closed. So, I just added checking is the connection still up. Of course, this below is not used in production, but just to show how it works.
Node.JS Code:
var net = require('net'),
fs = require('fs');
var path = '/tmp/echo.sock',
toSend = 1,
sended = 0;
fs.unlink(path, function () {
var server = net.createServer(function(c) {
console.log('server connected');
c.on('close', function() {
console.log('server disconnected');
});
c.write('hello\r\n');
c.on('data', function(data) {
console.log('Response: "' + data + '"');
if( data == "IS_ALREADY_CLOSED" & toSend == sended ) {
c.write('ALREADY_CLOSED');
return;
} else {
c.write('NOT_ALREADY_CLOSED');
return;
}
c.write('You said "' + data + '"');
sended++;
});
});
server.listen(path, function(e) {
console.log('server bound on %s', path);
});
});
process.on('uncaughtException', function (err) {
console.log( "UNCAUGHT EXCEPTION " );
console.log( "[Inside 'uncaughtException' event] " + err.stack || err.message );
});
And in PHP:
$fp = fsockopen("unix:///tmp/echo.sock", -1, $errno, $errstr);
if (!$fp) {
return "ERROR: $errno - $errstr<br />\n";
} else {
fwrite($fp, "Hello World <3");
do {
$output = fread($fp, 8192);
if($output == "ALREADY_CLOSED") break;
elseif( $output == "NOT_ALREADY_CLOSED" ) continue;
echo $output . "\n";
fwrite($fp, "IS_ALREADY_CLOSED");
} while(true);
fclose($fp);
}

Websocket does not receive messages

Server side:
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8000);
socket_listen($socket);
$client = socket_accept($socket);
$handshake = socket_read($client, 1024);
preg_match('/Sec-WebSocket-Key\: (.+?)\r\n/', $handshake, $accept);
$accept = base64_encode(sha1("$accept[1]258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
$handshake = "HTTP/1.1 101 Switching Protocols\r\n";
$handshake .= "Upgrade: websocket\r\n";
$handshake .= "Connection: Upgrade\r\n";
$handshake .= "Sec-WebSocket-Accept: $accept\r\n\r\n";
socket_write($client, $handshake.chr(0), strlen($handshake.chr(0)));
socket_write($client, 's'.chr(0));
sleep(5);
socket_close($client);
socket_close($socket);
?>
Client side:
<div id="output"></div>
<script>
if ("WebSocket" in window) {
var socket = new WebSocket('ws://127.0.0.1:8000');
socket.onopen = function() {
document.getElementById('output').innerHTML += 'socket open<br />';
}
socket.onmessage = function(msg) {
document.getElementById('output').innerHTML += 'new msg: '+msg.data+'<br />';
}
socket.onclose = function() {
document.getElementById('output').innerHTML += 'socket close';
}
}
</script>
I get "socket open" and after 5 seconds "socket close". I don't get the "s" sent by the server.
Tried on Firefox and Chrome.
What am I doing wrong?
Messages between client and server are not plain text. See the data framing section of the protocol spec for details on how to encode/decode messages.
There are plenty of code snippets in other SO questions (e.g. here) that might help get you started.

Can't send a message with the new websocket protocol

I am trying to develop a websocket server in php.
Here is what I have done so far :
(server part)
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server, "localhost", 10000);
socket_listen($server);
$client = socket_accept($server);
$message = socket_read($client, 5000);
$matches = array();
preg_match('#Sec-WebSocket-Key: (.*)\r\n#', $message, $matches);
$new_key = new_key($matches[1]);
$new_message = "HTTP/1.1 101 Switching Protocols\r\n";
$new_message .= "Upgrade: websocket\r\n";
$new_message .= "Connection: Upgrade\r\n";
$new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";
socket_write($client, $new_message, strlen($new_message));
$new_message = "Test message !";
socket_write($client, $new_message, strlen($new_message));
function new_key($key)
{
$key .= "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
$key = sha1($key);
$new_key = '';
for ($i = 0; $i < strlen($key); $i+=2)
{
$new_key .= chr(intval($key[$i] . $key[$i+1], 16));
}
$new_key = base64_encode($new_key);
return $new_key;
}
/* End of file server.php */
(client part)
window.onload = function() {
var ws = new WebSocket('ws://localhost:10000');
ws.onopen = function() {
alert('Connection open !');
setInterval(function() {
ws.send('lol');
}, 1000);
}
ws.onclose = function() {
alert('WebSocket close !');
}
ws.onmessage = function(e) {
alert(e.data);
}
ws.onerror = function(e) {
alert('Error');
}
};
The first socket_write works perfectly (for the handshake) and the open event is triggered correctly. But the second socket_write doesn't work. I tried to do a ws.send on the open event with a second socket_read in server part, it doesn't work neither.
Thank you if you have an idea !
I think it is a INVALID_STATE_ERR: DOM Exception 11 meaning a sync problem. Try this in your client:
var test = function(){
var myWebSocket = new WebSocket('ws://localhost:10000');
myWebSocket.onopen = function(e){
alert('connection open');
this.send('test1');
this.send('test2');
}
myWebSocket.onmessage = function(e){ alert('message ' + e.data) };
myWebSocket.onclose = function(e){ alert('connection closed'); this.close(); };
myWebSocket.send('test3');
};
test3 will fail because it is an asynchronous websocket.
I had a similar issue. After checking out this project over here https://github.com/srchea/PHP-Push-WebSocket I noticed a function called "encode" in this file https://github.com/srchea/PHP-Push-WebSocket/blob/master/lib/Server.class.php before sending the message.
So try to change this
socket_write($client, $new_message, strlen($new_message));
$new_message = "Test message !";
socket_write($client, $new_message, strlen($new_message));
to this
socket_write($client, $new_message, strlen($new_message));
$new_message = "Test message !";
socket_write($client, chr(129) . chr(strlen($new_message)) ."". $new_message);

Categories