I am making a chatroom using WebSockets, which is working fine when I use an unencrypted connection, but after I use a certificate it doesn't work anymore.
In JavaScript I was opening the connection to the WebSocket server at serverr.php like this:
var wsUri = "ws://mydomain.com:9002/chat/serverr.php";
websocket1 = new WebSocket(wsUri);
Now I know that I must use wss:// instead of ws:// so now I am using:
var wsUri = "wss://mydomain.com:9002/chat/serverr.php";
websocket1 = new WebSocket(wsUri);
But I get the following error:
WebSocket connection to 'wss://mydomain.com:9002/chat/serverr.php' failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR
But I don't know how to make a wss:// connection. I tried to modify my code with the following part:
set_time_limit(0);
require_once($_SERVER['DOCUMENT_ROOT']."../../../home/username/public_html/config/config.php");
$host = 'ssl://0.0.0.0'; //host
$port = '9002'; //port
$null = NULL; //null var
// Generate certificate
$privkey = openssl_pkey_new();
$cert = openssl_csr_new($dn, $privkey);
$cert = openssl_csr_sign($cert, null, $privkey, 365);
// Generate PEM file
# Optionally change the passphrase from 'comet' to whatever you want, or leave it empty for no passphrase
$pem_passphrase = 'comet';
$pem = array();
openssl_x509_export($cert, $pem[0]);
openssl_pkey_export($privkey, $pem[1], $pem_passphrase);
$pem = implode($pem);
// Save PEM file
$pemfile = 'server.pem';
file_put_contents($pemfile, $pem);
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_set_option($socket, SOL_SOCKET, 'ssl', 'local_cert', $pemfile);
socket_set_option($socket, SOL_SOCKET, 'ssl', 'passphrase', $pem_passphrase);
socket_set_option($socket, SOL_SOCKET, 'ssl', 'allow_self_signed', true);
socket_set_option($socket, SOL_SOCKET, 'ssl', 'verify_peer', false);
//bind socket to specified host
socket_bind($socket, 0, $port);
//the rest of code is still unmodified is like in the page serverr.php
Code in serverr.php
set_time_limit(0);
require_once($_SERVER['DOCUMENT_ROOT']."../../../home/username/public_html/config/config.php");
$host = 'localhost'; //host
$port = '9002'; //port
$null = NULL; //null var
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
//bind socket to specified host
socket_bind($socket, 0, $port);
//listen to port
socket_listen($socket);
perform_handshaking($header, $socket_new, $host, $port);
//create & add listning socket to the list
$clients = array($socket);
//start endless loop, so that our script doesn't stop
while (true) {
//manage multipal connections
$changed = $clients;
//returns the socket resources in $changed array
socket_select($changed, $null, $null, 0, 10);
//check for new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket); //accpet new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read($socket_new, 1024); //read data sent by the socket
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
//luam ultimele 15 mesaje start
$cerereinitialachat=mysqli_query($conexiune,"SELECT * FROM `chat_messages` ORDER BY `datesend` DESC LIMIT 17");
$obiectinitialchat=null;
$obiectobjectcount=0;
while ($rezultat=mysqli_fetch_assoc($cerereinitialachat)) {
$row=$rezultat;
$id;
$sender_steamid;
$avatar;
$sender_name;
$message;
$datesend;
$steamprofile;
$color;
foreach($row as $key=>$value){
if($key=="id"){
$id=$value;
}
if($key=="sender_steamid"){
$sender_steamid=$value;
}
if($key=="avatar"){
$avatar=$value;
}
if($key=="sender_name"){
$sender_name=$value;
}
if($key=="message"){
$message=$value;
}
if($key=="datesend"){
$datesend=$value;
}
if($key=="steamprofile"){
$steamprofile=$value;
}
if($key=="color"){
$color=$value;
}
}
$obiectinitialchat[$obiectobjectcount]=new stdClass;
$obiectinitialchat[$obiectobjectcount]->avatar=$avatar;
$obiectinitialchat[$obiectobjectcount]->name=$sender_name;
$obiectinitialchat[$obiectobjectcount]->message=$message;
$obiectinitialchat[$obiectobjectcount]->datesend=$datesend;
$obiectinitialchat[$obiectobjectcount]->steamprofile=$steamprofile;
$obiectinitialchat[$obiectobjectcount]->color=$color;
$obiectobjectcount=$obiectobjectcount+1;
}
//luam ultimele 15 mesaje stop
$cererenumaruonline=mysqli_query($conexiune,"SELECT * FROM `users` WHERE `online`!='0'");
$numaruonline=mysqli_num_rows($cererenumaruonline);
socket_getpeername($socket_new, $ip); //get ip address of connected socket
$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected', 'uonline'=>$numaruonline, 'lastmessages'=>$obiectinitialchat))); //prepare json data
send_message($response); //notify all users about new connection
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
//loop through all connected sockets
foreach ($changed as $changed_socket) {
//check for any incomming data
while(socket_recv($changed_socket, $buf, 1024, 0) >= 1){
$received_text = unmask($buf); //unmask data
$tst_msg = json_decode($received_text); //json decode
$user_steamid = esc($conexiune,$tst_msg->steamid); //sender steamid
$user_avatar = esc($conexiune,$tst_msg->avatar); //avatar
$user_name = esc($conexiune,$tst_msg->name); //sender name
$user_message = esc($conexiune,$tst_msg->message); //message text
$user_steamprofile = esc($conexiune,$tst_msg->steamprofile); //steamprofile
$user_message_date = time(); //message text date
$user_message=preg_replace("/\r|\n/", "", $user_message);//scoate enterurile
if (ctype_space($user_message)) {
//daca e numai spatiii libere(albe)
$user_message=preg_replace('/\s+/', "", $user_message);//scoate spatiile albe
}
$admin;
$color="normal";
$raspuns=mysqli_query($conexiune,"SELECT * FROM `users` WHERE `steamid`='".$user_steamid."'");
while($rezultat=mysqli_fetch_assoc($raspuns)){
$row=$rezultat;
foreach($row as $key=>$value){
if($key=="dirijor"){
$admin=$value;
}
}
}
if($admin=="Yes" || $user_steamid=="76561197997524415"){
$color="red";
}
if($user_steamid!="" && $user_steamid!=null && $user_message!="" && $user_message!=null){
mysqli_query($conexiune,"INSERT INTO `chat_messages` (`sender_steamid`,`avatar`,`sender_name`,`message`,`datesend`,`steamprofile`,`color`) VALUES ('".$user_steamid."','".$user_avatar."','".$user_name."','".$user_message."','".$user_message_date."','".$user_steamprofile."','".$color."')");
//prepare data to be sent to client
$response_text = mask(json_encode(array('type'=>'usermsg', 'avatar'=>$user_avatar, 'name'=>$user_name, 'message'=>$user_message, 'datesend'=>$user_message_date, 'steamprofile'=>$user_steamprofile, 'color'=>$color)));
send_message($response_text); //send data
}
break 2; //exist this loop
}
$buf = #socket_read($changed_socket, 1024, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
$cererenumaruonline2=mysqli_query($conexiune,"SELECT * FROM `users` WHERE `online`!='0'");
$numaruonline2=mysqli_num_rows($cererenumaruonline);
$response = mask(json_encode(array('type'=>'upadateusersonline','uonline'=>$numaruonline)));
send_message($response);
//notify all users about disconnected connection
//$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
//send_message($response);
}
}
}
// close the listening socket
socket_close($sock);
function send_message($msg)
{
global $clients;
foreach($clients as $changed_socket)
{
#socket_write($changed_socket,$msg,strlen($msg));
}
return true;
}
//Unmask incoming framed message
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
//Encode message for transfer to client.
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
//handshake new client.
function perform_handshaking($receved_header,$client_conn, $host, $port)
{
$headers = array();
$lines = preg_split("/\r\n/", $receved_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')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
Related
I would like to know, how do you store date in socket stream ?
I'm learning php socket atm, and for example, if i want to make an online users list : People on the webpage have a session[username]. I want to link it to the IP address in socket clients list.
I don't want to get the session_id of the client in socket page, i would like to send the username to that socket page (via javascript socket.onopen) and then the username would be stored until connection end.
Is that possible ?
EDIT
/* SERVER DATA
=======================================================*/
$host = '127.0.0.1'; //host
$port = '8090'; //port
$null = NULL; //null var
//Create TCP/IP, IPv4 stream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//Reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
//Bind socket to specified host
socket_bind($socket, 0, $port);
//Listen to port
socket_listen($socket);
//Create & add listening socket to the list
$clients = array($socket);
//Start endless loop, so that our script doesn't stop
while (true) {
//Manage multiple connections
$changed = $clients;
//Returns the socket resources in $changed array
socket_select($changed, $null, $null, 0, 10);
//Check for new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket); //accept new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read($socket_new, 1024); //read data sent by the socket
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
socket_getpeername($socket_new, $ip); //get ip address of connected socket
$response = mask(json_encode(array('type'=>'system_user_conn', 'message'=>$ip))); //prepare json data
send_message($response); //notify all users about new connection
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
//loop through all connected sockets
foreach ($changed as $changed_socket) {
//check for any incomming data
while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
{
$received_text = unmask($buf); //unmask data
$tst_msg = json_decode($received_text); //json decode
$user_name = $tst_msg->name; //sender name
$user_message = $tst_msg->message; //message text
//prepare data to be sent to client
$response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message)));
send_message($response_text); //send data
break 2; //exist this loop
}
$buf = #socket_read($changed_socket, 1024, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
send_message($response);
}
}
}
// close the listening socket
socket_close($socket);
function send_message($msg)
{
global $clients;
foreach($clients as $changed_socket)
{
#socket_write($changed_socket,$msg,strlen($msg));
}
return true;
}
//Unmask incoming framed message
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
//Encode message for transfer to client.
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
//handshake new client.
function perform_handshaking($receved_header,$client_conn, $host, $port)
{
$headers = array();
$lines = preg_split("/\r\n/", $receved_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')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
I would like to send 'message'=>$username.
At this line :
$response = mask(json_encode(array('type'=>'system_user_conn', 'message'=>$ip))); //prepare json data
When i'm using on send data (javascript), i re-send the username all the time, like this :
$('#frmChat').on("submit",function(event){
event.preventDefault();
var messageJSON = {
type: 'usrmsg',
name: '<?php echo $SESSION['pseudo']; ?>',
message: $('#chat-message').val()
};
websocket.send(JSON.stringify(messageJSON));
});
I'm looking for a way to store the username.
Not to re-send it all the time.
It will help me to create an "online users" list.
Thank you in advance.
Why would you do that?
You can just use the PHP Session Variable to check if a user is logged in.
You can specify the time a session will be stored in the PHP configuration.
You can also remove the session if needed.
I am a new developer with PHP socket.
Now i'm tto send data from my PHP code to socket server, but something error occur:
This is my PHP code for Send message to sockets server.
$host = 'localhost'; //host
$port = '9000'; //port
//create socket
$sock=socket_create(AF_INET,SOCK_STREAM,0) or die("Could not create the socket\n");
//connect to the server
$csock=socket_connect($sock,$host,$port) or die("Could not connect to server\n");
echo "Client socket connected!<br>";
$msg = mask(json_encode(array('type'=>'usermsg', 'name'=>'udom1', 'message'=>'Hello word', 'color'=>'FF7000')));
socket_send($csock,$msg,strlen($msg),0);
socket_write($csock, $msg);
socket_close($csock);
This is my PHP socket server script:
It's use for send receive data from client side.
<?php
$host = 'localhost'; //host
$port = '9000'; //port
$null = NULL; //null var
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
//bind socket to specified host
socket_bind($socket, 0, $port);
//listen to port
socket_listen($socket);
//create & add listning socket to the list
$clients = array($socket);
//start endless loop, so that our script doesn't stop
while (true) {
//manage multipal connections
$changed = $clients;
//returns the socket resources in $changed array
socket_select($changed, $null, $null, 0, 10);
//check for new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket); //accpet new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read($socket_new, 1024); //read data sent by the socket
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
socket_getpeername($socket_new, $ip); //get ip address of connected socket
$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data
send_message($response); //notify all users about new connection
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
//loop through all connected sockets
foreach ($changed as $changed_socket) {
//check for any incomming data
while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
{
$received_text = unmask($buf); //unmask data
$tst_msg = json_decode($received_text); //json decode
$user_name = $tst_msg->name; //sender name
$user_message = $tst_msg->message; //message text
$user_color = $tst_msg->color; //color
//prepare data to be sent to client
$response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color)));
send_message($response_text); //send data
break 2; //exist this loop
}
$buf = #socket_read($changed_socket, 1024, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
send_message($response);
}
}
}
// close the listening socket
socket_close($socket);
function send_message($msg)
{
global $clients;
foreach($clients as $changed_socket)
{
#socket_write($changed_socket,$msg,strlen($msg));
}
return true;
}
//Unmask incoming framed message
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
//Encode message for transfer to client.
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
//handshake new client.
function perform_handshaking($receved_header,$client_conn, $host, $port)
{
$headers = array();
$lines = preg_split("/\r\n/", $receved_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')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
?>
How can I fix this trouble?
Please help me.
Thank you in advance.
change your script :
//loop through all connected sockets
foreach ($changed as $changed_socket) {
//check for any incomming data
while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
{.......
with
//loop through all connected sockets
foreach ($changed as $changed_socket) {
//check for any incomming data
$bytesocket=#socket_recv($changed_socket, $buf, 1024, 0);
while($bytesocket >= 1)
{.......
I have a websocket server running by PHP using socket_create().
I am using following code :
function customError($errno, $errstr, $errfile, $errline) {
$theerror= "Error [$errno] in $errfile on line $errline : $errstr ";
$errorlogfile = fopen(date("d_m_y")."socket.log", "a");
fwrite($errorlogfile, PHP_EOL.date("h:i:s").' - '.$theerror);
fclose($errorlogfile);
}
set_error_handler("customError");
function wmlog($log){
$f=fopen(date("d_m_y").'socket.log','a');
fwrite($f, $log." \r\n ");
fclose($f);
}
$wmdir=dirname(__FILE__);
$host = 'srvdb';
$port = $argv[1];
/* $ccode=$argv[4];
$uid=$argv[3] ;
$cid=$argv[4]; */
$null = NULL; //host
if(!$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP){
wmlog("ERROR creating socket") ;
}else{
wmlog("socket created") ;
}
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);//reuseable port
socket_bind($socket, $host, $port);//bind socket to specified host
socket_listen($socket);//listen to port
$clients = array($socket);//create & add listning socket to the list
include_once($wmdir.'/intochat_f.php');
//include_once($wmdir.'/include1.php');
wmlog("included") ;
//start endless loop, so that our script doesn't stop
while (true) {//manage multipal connections
$changed = $clients;
socket_select($changed, $null, $null, 0, 10);//returns the socket resources in $changed array
///////// AD NEW SOCKET ///////
// $a_pv - passed values ()
if (in_array($socket, $changed)) {//check for new socket
$socket_new = socket_accept($socket); //accpet new socket
$header = socket_read($socket_new, 1024); //read data sent by the socket
$a_h=explode(PHP_EOL, $header);
$s_get=$a_h[0];
unset($a_h[0]) ;
$a_header=array();
foreach($a_h as $v){
$nk=strtok($v, ":");
$nv=substr($v, (strrpos($v, ':') ?: -1) +1);
$a_header[$nk]=$nv;
}
$a_pv=explode('_', $s_get);
$a_pv[0] = $a_header['Sec-WebSocket-Protocol'];
$pid=$a_pv[1];
$clients[$pid] = $socket_new; //add socket to client array
wmlog('HEADER: '. " \r\n ". $header. " \r\n EOF HEADER ");
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
wmlog((socket_getpeername($socket_new, $ip))." ip: ".$ip. "\r\n") ; //get ip address of connected socket
//$response = mask(json_encode(array('act2'=>30))); //prepare json data
//send_message($response, $pid); //notify all users about new connection
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
//loop through all connected sockets
foreach ($changed as $socketid => $changed_socket) {
//check for any incomming data and do smth with it
while(socket_recv($changed_socket, $buf, 1024, 0) >= 1) {
$received_text = unmask($buf);
$msg = json_decode($received_text);//unmask data AND json decode
// PUT MESSAGE TO DB ////
/// SEND MESSAGE TO OTHERS (priv or everybody )///
if(isset($msg->to) && $msg->to >0 ){
$scopeid=$msg->to;
}else{
$scopeid=0;
}
//$a_response=$msg.
//prepare data to be sent to client
$response_text = mask(json_encode(array('val1'=>$msg->val1, 'val2'=>$msg->val2, 'from'=>$socketid )));
send_message($response_text, $scopeid); //send data
break 2; //exist this loop
}
$buf = #socket_read($changed_socket, 1024, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
$response = mask(json_encode(array('val1'=>'somebody left', 'val2'=>' left user')));
send_message($response);
}
}
}
socket_close($socket);
function send_message($msg, $id=0){
global $clients;
if($id==0){ // send message to everybody
foreach($clients as $changed_socket){
#socket_write($changed_socket,$msg,strlen($msg));
}
}else{ // send message to selected socket
#socket_write($clients[$id],$msg,strlen($msg));
}
return true;
}
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}else{
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
function mask($text){
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
function perform_handshaking($receved_header,$client_conn, $host, $port) {
$headers = array();
$lines = preg_split("/\r\n/", $receved_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')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
If I use connect to it from browser (using javascript new WebSocket(wsUri); ) - it works fine, but when I try to connect to it from PHP script using fsockopen(), data after unmasking looks gibberish but like valid JSON before unmasking.
And the question is - why is unmasking not working when sending data via PHP fsockopen / how to make it work?
I found by google in one forum this (tools.ietf.org/html/rfc6455):
A server MUST NOT mask any frames that it sends to the client.
A client MUST close a connection if it detects a masked
frame.
I'm running a coin flip game website (people can play against each other). So far I used a php request to mysql and refresh it every 5s - it worked great. But, with bigger amount of users, there is a problem, site starts to be slow.
This is my server specification:
2 CPU, 2.5+ GHz Processor
4 GB Ram
240 GB SSD Disk
Transfer Unlimited
1 Gbps Connection
I'm also running a socket based chat on site - I thought I can use sockets to display game list.
Here is a server.php, used for chat:
<?php
$host = '188.209.49.96'; //host
$port = '9001'; //port
$null = NULL; //null var
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
//bind socket to specified host
socket_bind($socket, 0, $port);
//listen to port
socket_listen($socket);
//create & add listning socket to the list
$clients = array($socket);
//start endless loop, so that our script doesn't stop
while (true) {
//manage multipal connections
$changed = $clients;
//returns the socket resources in $changed array
socket_select($changed, $null, $null, 0, 10);
//check for new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket); //accpet new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read($socket_new, 1024); //read data sent by the socket
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
//socket_getpeername($socket_new, $ip); //get ip address of connected socket
//$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data
//send_message($response); //notify all users about new connection
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
//loop through all connected sockets
foreach ($changed as $changed_socket) {
//check for any incomming data
while(socket_recv($changed_socket, $buf, 1024, 0) != 0)
{
$received_text = unmask($buf); //unmask data
$tst_msg = json_decode($received_text); //json decode
if($tst_msg != NULL){
$user_name = $tst_msg->name; //sender name
$user_message = $tst_msg->message; //message text
$user_color = $tst_msg->color; //color
$user_avatar = $tst_msg->avatar;
//prepare data to be sent to client
$response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color, 'avatar'=>$user_avatar)));
send_message($response_text); //send data
break 2; //exist this loop
}
}
$buf = #socket_read($changed_socket, 1024, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
//$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
//send_message($response);
}
}
}
// close the listening socket
socket_close($socket);
function send_message($msg)
{
global $clients;
foreach($clients as $changed_socket)
{
#socket_write($changed_socket,$msg,strlen($msg));
}
return true;
}
//Unmask incoming framed message
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
//Encode message for transfer to client.
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
//handshake new client.
function perform_handshaking($receved_header,$client_conn, $host, $port)
{
$headers = array();
$lines = preg_split("/\r\n/", $receved_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')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
This is Ratchet WebSockets based script.
I want to have and chat, and game list socket-based on my site.
How can I get mysql data and make it display (and obviously refresh) with socket?
Thank you for help.
Im creating "communication" with websockets. (thanks: http://www.sanwebe.com/2013/05/chat-using-websocket-php-socket), the communication works very well, but Im trying to save some date when it goes through the "websocket server"(?)
I have created the socket ws_server.php
<?php
require_once('filegenerator.php');
$filegenerator = new FileGenerator();
$host = '127.0.0.1'; //host
$port = '9000'; //port
$null = NULL; //null var
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
//bind socket to specified host
socket_bind($socket, 0, $port);
//listen to port
socket_listen($socket);
//create & add listning socket to the list
$clients = array($socket);
//start endless loop, so that our script doesn't stop
while (true) {
//manage multipal connections
$changed = $clients;
//returns the socket resources in $changed array
socket_select($changed, $null, $null, 0, 10);
//check for new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket); //accpet new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read($socket_new, 1024); //read data sent by the socket
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
socket_getpeername($socket_new, $ip); //get ip address of connected socket
$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data
send_message($response); //notify all users about new connection
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
//loop through all connected sockets
foreach ($changed as $changed_socket) {
//check for any incomming data
while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
{
$received_text = unmask($buf); //unmask data
$tst_msg = json_decode($received_text); //json decode
if ($tst_msg->type == 'order') {
filegen( 'String for testing',$filegenerator );
$items_to_kitchen = $tst_msg->order->items;
foreach ($items_to_kitchen as $key => $value) {
$msg_to_kitchen[$key] = $value;
}
$response_text = mask(json_encode(array('order'=>$msg_to_kitchen)));
} elseif ($tst_msg->type == 'kitchen') {
$response_text = mask(json_encode(array('type'=>$tst_msg->type,'kitchenstate'=>$tst_msg)));
}
send_message($response_text); //send data
break 2; //exist this loop
}
$buf = #socket_read($changed_socket, 1024, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
$response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
send_message($response);
}
}
}
// close the listening socket
socket_close($sock);
function send_message($msg)
{
global $clients;
foreach($clients as $changed_socket)
{
#socket_write($changed_socket,$msg,strlen($msg));
}
return true;
}
//Unmask incoming framed message
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
//Encode message for transfer to client.
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
//handshake new client.
function perform_handshaking($receved_header,$client_conn, $host, $port)
{
$headers = array();
$lines = preg_split("/\r\n/", $receved_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')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/xxx/includes/ws_server.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));
}
The client sends the data with $tst_msg->type == 'order' .. then I wants to create json file to save it. The class of file generation is in filegenerator.php
<?php
class FileGenerator{
private $_filename;
private $_data;
public function write($str_filename,$str_data){
$this->_filename = $str_filename;
$this->_data = $str_data;
$this->_checkPermission();
$this->_checkData();
$handle = fopen($str_filename,'w');
fwrite($handle, $str_data."\r\n");
fclose($handle);
}
public function test(){
echo "This string outputs in console";
// php -q ws_server.php
}
public function read($str_filename){
$this->_filename = $str_filename;
echo $this->_filename;
$this->_checkExists();
$handle = fopen($str_filename, 'r');
return file_get_contents($str_filename);
}
private function _checkPermission(){
if ( !is_writable($this->_filename)) {
die('Change your CHMOD permissions to:'.$this->_filename);
}
}
private function _checkData(){
if (strlen($this->_data) < 1) {
die('You must have more than one character for data');
}
}
private function _checkExists(){
if (!file_exists($this->_filename)) {
die('The File does not exis');
}
}
}
function filegen( $str,$filegenerator ){
$filegenerator->test();
$filegenerator->write('test.json',$str);
}
?>
When I call the function filegen() at line 58 in ws_server.php ,
filegen( 'String for testing',$filegenerator );
at the permission check the program die(). But
The file is writable, full access (for testing purposes)
It exists
Interesting thin, when I create another file for testing the FileGenerator class it works perfectly, but doesnt from ws_server.php file
Im using xampp on windows
The console run: php -q D:\xampp\htdocs\xxx\includes\ws_server.php
I tried simply put
$handle = fopen($str_filename,'w');
fwrite($handle, $str_data."\r\n");
fclose($handle);
but same issue occurs. Interesting thing, that I can get $handle #id if I echo, and echoing fwrite() can return the the number of characters, but the file doesnt change!
Can somebody help me, describe me what am I doing wrong! Thank you
I think it's a path problem or a file ownership problem.
Try $filegenerator->write(__DIR__ . '/test.json, $str) to make sure it tries to write test.json in the directory the file is in.
Check who the file owner on the filesystem is. Webservers often have their own user (www-data for example), which might conflict with your own logged in user. You might have to chown the file.