I'm trying to connect a PHP-based client to a websocket server.
Here's the code I have been using which has been widely published on different forums. But for some reason I just cannot get it to work.
Any help would be appreciated.
$host = 'host'; //where is the websocket server
$port = 443; //ssl
$local = "http://www.example.com/"; //url where this script run
$data = '{"id": 2,"command": "server_info"}'; //data to be send
$head = "GET / HTTP/1.1"."\r\n".
"Upgrade: WebSocket"."\r\n".
"Connection: Upgrade"."\r\n".
"Origin: $local"."\r\n".
"Host: $host"."\r\n".
"Content-Length: ".strlen($data)."\r\n"."\r\n";
////WebSocket handshake
$sock = fsockopen($host, $port, $errno, $errstr, 2);
fwrite($sock, $head ) or die('error:'.$errno.':'.$errstr);
$headers = fread($sock, 2000);
fwrite($sock, "\x00$data\xff" ) or die('error:'.$errno.':'.$errstr);
$wsdata = fread($sock, 2000); //receives the data included in the websocket package "\x00DATA\xff"
$retdata = trim($wsdata,"\x00\xff"); //extracts data
////WebSocket handshake
fclose($sock);
echo $retdata;
I would probably prefer to use an existing websocket client library (maybe https://github.com/gabrielbull/php-websocket-client or https://github.com/Devristo/phpws/tree/master/src/Devristo/Phpws/Client ?) rather than roll your own, but I got it to at least connect by using:
$head = "GET / HTTP/1.1"."\r\n".
"Host: $host"."\r\n".
"Upgrade: websocket"."\r\n".
"Connection: Upgrade"."\r\n".
"Sec-WebSocket-Key: asdasdaas76da7sd6asd6as7d"."\r\n".
"Sec-WebSocket-Version: 13"."\r\n".
"Content-Length: ".strlen($data)."\r\n"."\r\n";
My server is using TLS/SSL, so I also needed:
$sock = fsockopen('tls://'.$host, $port, $errno, $errstr, 2);
The full protocol spec is: https://tools.ietf.org/rfc/rfc6455.txt
UPDATE 2019: many servers requires the key to be more unique that the original example, resulting in failure to establish upgrade connection. The key generation is now changed accordingly.
Your header must contain:
Sec-WebSocket-Key: (some value)
Sec-WebSocket-Version: 13
to connect successfully.
When you have made the connection, you also need to use the hybi10 frame encoding.
See: https://tools.ietf.org/rfc/rfc6455.txt - Its a bit dry though.
I have made this working example:
<?php
$sp=websocket_open('127.0.0.1/ws_request.php?param=php_test',$errstr);
websocket_write($sp,"Websocket request message");
echo websocket_read($sp,true);
$sp=websocket_open('127.0.0.1:8080/ws_request.php?param=php_test',$errstr);
websocket_write($sp,"Websocket request message");
echo websocket_read($sp,true);
function websocket_open($url){
$key=base64_encode(openssl_random_pseudo_bytes(16));
$query=parse_url($url);
$header="GET / HTTP/1.1\r\n"
."pragma: no-cache\r\n"
."cache-control: no-cache\r\n"
."Upgrade: WebSocket\r\n"
."Connection: Upgrade\r\n"
."Sec-WebSocket-Key: $key\r\n"
."Sec-WebSocket-Version: 13\r\n"
."\r\n";
$sp=fsockopen($query['host'],$query['port'], $errno, $errstr,1);
if(!$sp) die("Unable to connect to server ".$url);
// Ask for connection upgrade to websocket
fwrite($sp,$header);
stream_set_timeout($sp,5);
$reaponse_header=fread($sp, 1024);
if(!strpos($reaponse_header," 101 ")
|| !strpos($reaponse_header,'Sec-WebSocket-Accept: ')){
die("Server did not accept to upgrade connection to websocket"
.$reaponse_header);
}
return $sp;
}
function websocket_write($sp, $data,$final=true){
// Assamble header: FINal 0x80 | Opcode 0x02
$header=chr(($final?0x80:0) | 0x02); // 0x02 binary
// Mask 0x80 | payload length (0-125)
if(strlen($data)<126) $header.=chr(0x80 | strlen($data));
elseif (strlen($data)<0xFFFF) $header.=chr(0x80 | 126) . pack("n",strlen($data));
elseif(PHP_INT_SIZE>4) // 64 bit
$header.=chr(0x80 | 127) . pack("Q",strlen($data));
else // 32 bit (pack Q dosen't work)
$header.=chr(0x80 | 127) . pack("N",0) . pack("N",strlen($data));
// Add mask
$mask=pack("N",rand(1,0x7FFFFFFF));
$header.=$mask;
// Mask application data.
for($i = 0; $i < strlen($data); $i++)
$data[$i]=chr(ord($data[$i]) ^ ord($mask[$i % 4]));
return fwrite($sp,$header.$data);
}
function websocket_read($sp,$wait_for_end=true,&$err=''){
$out_buffer="";
do{
// Read header
$header=fread($sp,2);
if(!$header) die("Reading header from websocket failed");
$opcode = ord($header[0]) & 0x0F;
$final = ord($header[0]) & 0x80;
$masked = ord($header[1]) & 0x80;
$payload_len = ord($header[1]) & 0x7F;
// Get payload length extensions
$ext_len = 0;
if($payload_len >= 0x7E){
$ext_len = 2;
if($payload_len == 0x7F) $ext_len = 8;
$ext=fread($sp,$ext_len);
if(!$ext) die("Reading header extension from websocket failed");
// Set extented paylod length
$payload_len= 0;
for($i=0;$i<$ext_len;$i++)
$payload_len += ord($header[$i]) << ($ext_len-$i-1)*8;
}
// Get Mask key
if($masked){
$mask=fread($sp,4);
if(!$mask) die("Reading header mask from websocket failed");
}
// Get payload
$frame_data='';
do{
$frame= fread($sp,$payload_len);
if(!$frame) die("Reading from websocket failed.");
$payload_len -= strlen($frame);
$frame_data.=$frame;
}while($payload_len>0);
// if opcode ping, reuse headers to send a pong and continue to read
if($opcode==9){
// Assamble header: FINal 0x80 | Opcode 0x02
$header[0]=chr(($final?0x80:0) | 0x0A); // 0x0A Pong
fwrite($sp,$header.$ext.$mask.$frame_data);
// Recieve and unmask data
}elseif($opcode<3){
$data="";
if($masked)
for ($i = 0; $i < $data_len; $i++)
$data.= $frame_data[$i] ^ $mask[$i % 4];
else
$data.= $frame_data;
$out_buffer.=$data;
}
// wait for Final
}while($wait_for_end && !$final);
return $out_buffer;
}
You can get the full version here: https://github.com/paragi/PHP-websocket-client
Connecting to a WSS stream with purely php:
Example with the public binance wss api.
<?php
$sock = stream_socket_client("tls://stream.binance.com:9443",$error,$errnum,30,STREAM_CLIENT_CONNECT,stream_context_create(null));
if (!$sock) {
echo "[$errnum] $error" . PHP_EOL;
} else {
echo "Connected - Do NOT get rekt!" . PHP_EOL;
fwrite($sock, "GET /stream?streams=btcusdt#kline_1m HTTP/1.1\r\nHost: stream.binance.com:9443\r\nAccept: */*\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: ".rand(0,999)."\r\n\r\n");
while (!feof($sock)) {
var_dump(explode(",",fgets($sock, 512)));
}
}
More details: WebSockets - send json data via php
https://github.com/ratchetphp/Pawl
I tried around 10 different solutions from various stackoverflow threads but nothing worked, after spending about 6 hours trying different solution this worked for me.
scenario:
Ratchet as server
I was able to connect via reactjs
I wasn't able to connect via php,
Expected Result: To send message from php-client to all connected react clients. the git repo i provided was a lucky break i was looking for.
I tried the solution presented here and it works fine for me.
here are the details:
step1: Install the library from here with non-root user as follows:
php8.0 composer require textalk/websocket
then use the code below for sending some message to a socket which is located on localhost and has port number 8080:
<?php
require('vendor/autoload.php');
use WebSocket\Client;
$client = new Client("ws://127.0.0.1:8080");
$client->send($argv[1]);
?>
Since I had php7.1 webserver and the socket was installed with php8.0, I put the above code in a PHP file (testphp.php) and call it using shell_exec('php8.0 testphp.php hello');
The 400 error is because you're missing Host and Origin in the header.
$key=base64_encode(openssl_random_pseudo_bytes(16));
$query=parse_url($url);
$local = "http://".$query['host'];
if (isset($_SERVER['REMOTE_ADDR'])) $local = "http://".$_SERVER['REMOTE_ADDR'];
$header="GET / HTTP/1.1\r\n"
."Host: ".$query['host']."\r\n"
."Origin: ".$local."\r\n"
."Pragma: no-cache\r\n"
."Cache-Control: no-cache\r\n"
."Upgrade: websocket\r\n"
."Connection: Upgrade\r\n"
."Sec-WebSocket-Key: $key\r\n"
."Sec-WebSocket-Version: 13\r\n"
."\r\n";
Related
I have the following code, this was previously working and now all of a sudden I am getting an error;
The error I am getting is;
Failed to connect to server Server responed with: Server did not accept to upgrade connection to websocket.HTTP/1.1 200 OK Date: Sun, 22 Aug 2021 01:07:27 GMT Content-Type: text/html Transfer-Encoding: chunked Connection: keep-alive Last-Modified: Fri, 05 Mar 2021 07:33:32 GMT X-By: #XRPLF X-Upgrade: WebSocket X-Conn: upgrade CF-Cache-Status: DYNAMIC Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=ahbUvdpOxo1wZb%2B54qo5pEWE0KGc%2BTpWu2vgw47WhbCgjbfPwdQOGLCAZlivJyijhHs4PTt4nYVIW3ak%2BwAtlz6qhz36saYBmLZ3%2FyKJc8ZB6OJA0%2FNVp14%3D"}],"group":"cf-nel","max_age":604800} NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800} Server: cloudflare CF-RAY: 682834517edc2ce3-LHR alt-svc: h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400 6980
I am not too sure what is causing it below is the code;
<?php
include('/websocket_client.php');
$server = 'xrpl.ws';
$command = json_encode(array(
'id' => 2,
'command' => "server_info"
));
if( $sp = websocket_open($server, 443,'',$errstr, 10, true) ) {
websocket_write($sp,$command);
$result = websocket_read($sp,$errstr);
}else {
echo "Failed to connect to server\n";
echo "Server responed with: $errstr\n";
}
$result_data = json_decode($result, true);
echo '<pre>';
echo $result_data;
echo '</pre>';
?>
Below is the Websocket_Client.php page I am sorry for the length ; But I thought it might be important to include it all.
<?php
/*----------------------------------------------------------------------------*\
Websocket client - https://github.com/paragi/PHP-websocket-client
By Paragi 2013, Simon Riget MIT license.
This is a demonstration of a websocket clinet.
If you find flaws in it, please let me know at simon.riget (at) gmail
Websockets use hybi10 frame encoding:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/63) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
See: https://tools.ietf.org/rfc/rfc6455.txt
or: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10#section-4.2
\*----------------------------------------------------------------------------*/
/*============================================================================*\
Open websocket connection
resource websocket_open(string $host [,int $port [,$additional_headers [,string &error_string ,[, int $timeout]]]]
host
A host URL. It can be a domain name like www.example.com or an IP address,
with port number. Local host example: 127.0.0.1:8080
port
headers (optional)
additional HTTP headers to attach to the request.
For example to parse a session cookie: "Cookie: SID=" . session_id()
error_string (optional)
A referenced variable to store error messages, i any
timeout (optional)
The maximum time in seconds, a read operation will wait for an answer from
the server. Default value is 10 seconds.
ssl (optional)
persistant (optional)
path (optional)
Context (optional)
Open a websocket connection by initiating a HTTP GET, with an upgrade request
to websocket.
If the server accepts, it sends a 101 response header, containing
"Sec-WebSocket-Accept"
\*============================================================================*/
function websocket_open($host='',$port=80,$headers='',&$error_string='',$timeout=10,$ssl=false, $persistant = false, $path = '/', $context = null){
// Generate a key (to convince server that the update is not random)
// The key is for the server to prove it i websocket aware. (We know it is)
$key=base64_encode(openssl_random_pseudo_bytes(16));
$header = "GET " . $path . " HTTP/1.1\r\n"
."Host: $host\r\n"
."pragma: no-cache\r\n"
."Upgrade: WebSocket\r\n"
."Connection: Upgrade\r\n"
."Sec-WebSocket-Key: $key\r\n"
."Sec-WebSocket-Version: 13\r\n";
// Add extra headers
if(!empty($headers)) foreach($headers as $h) $header.=$h."\r\n";
// Add end of header marker
$header.="\r\n";
// Connect to server
$host = $host ? $host : "127.0.0.1";
$port = $port <1 ? ( $ssl ? 443 : 80 ): $port;
$address = ($ssl ? 'ssl://' : '') . $host . ':' . $port;
$flags = STREAM_CLIENT_CONNECT | ( $persistant ? STREAM_CLIENT_PERSISTENT : 0 );
$ctx = $context ?? stream_context_create();
$sp = stream_socket_client($address, $errno, $errstr, $timeout, $flags, $ctx);
if(!$sp){
$error_string = "Unable to connect to websocket server: $errstr ($errno)";
return false;
}
// Set timeouts
stream_set_timeout($sp,$timeout);
if (!$persistant or ftell($sp) === 0) {
//Request upgrade to websocket
$rc = fwrite($sp,$header);
if(!$rc){
$error_string
= "Unable to send upgrade header to websocket server: $errstr ($errno)";
return false;
}
// Read response into an assotiative array of headers. Fails if upgrade failes.
$reaponse_header=fread($sp, 1024);
// status code 101 indicates that the WebSocket handshake has completed.
if (stripos($reaponse_header, ' 101 ') === false
|| stripos($reaponse_header, 'Sec-WebSocket-Accept: ') === false) {
$error_string = "Server did not accept to upgrade connection to websocket."
.$reaponse_header. E_USER_ERROR;
return false;
}
// The key we send is returned, concatenate with "258EAFA5-E914-47DA-95CA-
// C5AB0DC85B11" and then base64-encoded. one can verify if one feels the need...
}
return $sp;
}
/*============================================================================*\
Write to websocket
int websocket_write(resource $handle, string $data ,[boolean $final])
Write a chunk of data through the websocket, using hybi10 frame encoding
handle
the resource handle returned by websocket_open, if successful
data
Data to transport to server
final (optional)
indicate if this block is the final data block of this request. Default true
binary (optional)
indicate if this block is sent in binary or text mode. Default true/binary
\*============================================================================*/
function websocket_write($sp,$data,$final=true,$binary=true){
// Assemble header: FINal 0x80 | Mode (0x02 binary, 0x01 text)
if ($binary)
$header=chr(($final?0x80:0) | 0x02); // 0x02 binary mode
else
$header=chr(($final?0x80:0) | 0x01); // 0x01 text mode
// Mask 0x80 | payload length (0-125)
if(strlen($data)<126) $header.=chr(0x80 | strlen($data));
elseif (strlen($data)<0xFFFF) $header.=chr(0x80 | 126) . pack("n",strlen($data));
else $header.=chr(0x80 | 127) . pack("N",0) . pack("N",strlen($data));
// Add mask
$mask=pack("N",rand(1,0x7FFFFFFF));
$header.=$mask;
// Mask application data.
for($i = 0; $i < strlen($data); $i++)
$data[$i]=chr(ord($data[$i]) ^ ord($mask[$i % 4]));
return fwrite($sp,$header.$data);
}
/*============================================================================*\
Read from websocket
string websocket_read(resource $handle [,string &error_string])
read a chunk of data from the server, using hybi10 frame encoding
handle
the resource handle returned by websocket_open, if successful
error_string (optional)
A referenced variable to store error messages, i any
Read
Note:
- This implementation waits for the final chunk of data, before returning.
- Reading data while handling/ignoring other kind of packages
\*============================================================================*/
function websocket_read($sp,&$error_string=NULL){
$data="";
do{
// Read header
$header=fread($sp,2);
if(!$header){
$error_string = "Reading header from websocket failed.";
return false;
}
$opcode = ord($header[0]) & 0x0F;
$final = ord($header[0]) & 0x80;
$masked = ord($header[1]) & 0x80;
$payload_len = ord($header[1]) & 0x7F;
// Get payload length extensions
$ext_len = 0;
if($payload_len >= 0x7E){
$ext_len = 2;
if($payload_len == 0x7F) $ext_len = 8;
$header=fread($sp,$ext_len);
if(!$header){
$error_string = "Reading header extension from websocket failed.";
return false;
}
// Set extented paylod length
$payload_len= 0;
for($i=0;$i<$ext_len;$i++)
$payload_len += ord($header[$i]) << ($ext_len-$i-1)*8;
}
// Get Mask key
if($masked){
$mask=fread($sp,4);
if(!$mask){
$error_string = "Reading header mask from websocket failed.";
return false;
}
}
// Get payload
$frame_data='';
while($payload_len>0){
$frame= fread($sp,$payload_len);
if(!$frame){
$error_string = "Reading from websocket failed.";
return false;
}
$payload_len -= strlen($frame);
$frame_data.=$frame;
}
// Handle ping requests (sort of) send pong and continue to read
if($opcode == 9){
// Assamble header: FINal 0x80 | Opcode 0x0A + Mask on 0x80 with zero payload
fwrite($sp,chr(0x8A) . chr(0x80) . pack("N", rand(1,0x7FFFFFFF)));
continue;
// Close
} elseif($opcode == 8){
fclose($sp);
// 0 = continuation frame, 1 = text frame, 2 = binary frame
}elseif($opcode < 3){
// Unmask data
$data_len=strlen($frame_data);
if($masked)
for ($i = 0; $i < $data_len; $i++)
$data.= $frame_data[$i] ^ $mask[$i % 4];
else
$data.= $frame_data;
}else
continue;
}while(!$final);
return $data;
}
?>
I thought initially I had been blacklisted or something for the amount of requests I was making and the fact that it in the message I saw something about CloudFlare but I used a VPN to navigate to xrpl.ws via the IP of the host and I was able to access this without problems. I have not made any changes to the PHP ini file either so I really am stuck to what is causing this. Thanks for any help and sorry for the length of the examples. Thanks again.
I did see this previous answer which mentioned about the way the key is generated but I looked into it and I believe its using a good generation method. So I really am at a loss.
The error message is pretty clear:
Server did not accept to upgrade connection to websocket.
You'd need Ratchet, because there likely is no web-socket support available on this server.
Or it may send out unexpected HTTP headers.
I using PHP SocketIO class to connect NodeJS application and send messages.
Everything worked wonderfully with Socket.io 2 but after upgrade to version 3 the PHP integration is stopped working.
When I send request I am getting this response:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: hNcappwZIQEbMz7ZGWS71lNcROc=
But I don't see anything on NodeJS side, even when I tried to log any connection to the server by using "connection" event.
This is the PHP class:
class SocketIO
{
/**
* #param null $host - $host of socket server
* #param null $port - port of socket server
* #param string $action - action to execute in sockt server
* #param null $data - message to socket server
* #param string $address - addres of socket.io on socket server
* #param string $transport - transport type
* #return bool
*/
public function send($host = null, $port = null, $action= "message", $data = null, $address = "/socket.io/?EIO=2", $transport = 'websocket')
{
$fd = fsockopen($host, $port, $errno, $errstr);
if (!$fd) {
return false;
} //Can't connect tot server
$key = $this->generateKey();
$out = "GET $address&transport=$transport HTTP/1.1\r\n";
$out.= "Host: https://$host:$port\r\n";
$out.= "Upgrade: WebSocket\r\n";
$out.= "Connection: Upgrade\r\n";
$out.= "Sec-WebSocket-Key: $key\r\n";
$out.= "Sec-WebSocket-Version: 13\r\n";
$out.= "Origin: https://$host\r\n\r\n";
fwrite($fd, $out);
// 101 switching protocols, see if echoes key
$result= fread($fd,10000);
preg_match('#Sec-WebSocket-Accept:\s(.*)$#mU', $result, $matches);
$keyAccept = trim($matches[1]);
$expectedResonse = base64_encode(pack('H*', sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$handshaked = ($keyAccept === $expectedResonse) ? true : false;
if ($handshaked){
fwrite($fd, $this->hybi10Encode('42["' . $action . '", "' . addslashes($data) . '"]'));
fread($fd,1000000);
return true;
} else {return false;}
}
private function generateKey($length = 16)
{
$c = 0;
$tmp = '';
while ($c++ * 16 < $length) { $tmp .= md5(mt_rand(), true); }
return base64_encode(substr($tmp, 0, $length));
}
private function hybi10Encode($payload, $type = 'text', $masked = true)
{
$frameHead = array();
$payloadLength = strlen($payload);
switch ($type) {
case 'text':
$frameHead[0] = 129;
break;
case 'close':
$frameHead[0] = 136;
break;
case 'ping':
$frameHead[0] = 137;
break;
case 'pong':
$frameHead[0] = 138;
break;
}
if ($payloadLength > 65535) {
$payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);
$frameHead[1] = ($masked === true) ? 255 : 127;
for ($i = 0; $i < 8; $i++) {
$frameHead[$i + 2] = bindec($payloadLengthBin[$i]);
}
if ($frameHead[2] > 127) {
$this->close(1004);
return false;
}
} elseif ($payloadLength > 125) {
$payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);
$frameHead[1] = ($masked === true) ? 254 : 126;
$frameHead[2] = bindec($payloadLengthBin[0]);
$frameHead[3] = bindec($payloadLengthBin[1]);
} else {
$frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;
}
foreach (array_keys($frameHead) as $i) {
$frameHead[$i] = chr($frameHead[$i]);
}
if ($masked === true) {
$mask = array();
for ($i = 0; $i < 4; $i++) {
$mask[$i] = chr(rand(0, 255));
}
$frameHead = array_merge($frameHead, $mask);
}
$frame = implode('', $frameHead);
for ($i = 0; $i < $payloadLength; $i++) {
$frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
}
return $frame;
}
}
Thank you for help!
I was having the same problem with all the libraries that exists on github, the problem is that they are abandoned or not updated to socket.io V3.
In socket.io documentation says:
TL;DR: due to several breaking changes, a v2 client will not be able to connect to a v3 server (and vice versa)
To solve this problem, you need to learn how socket.io client works, this is easy because is in the protocol documentation, in the sample-session section.
Socket.Io protocol documentation
To solve this, you will need to forget the fsockopen and fwrite functions, you need to use CURL directly doing the requests mentioned in the protocol documentation.
Request n°1
GET
url: /socket.io/?EIO=4&transport=polling&t=N8hyd7H
Open packet: Open the connection between php and socket.io server. The server will return a "session id" named "sid", you will be adding this to the url query for the subsecuent queries.
Request n°2
POST
url: /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=sessionIdFromRequest1
post body: '40'
Namespace connection request: You need to send in the body the number 40, as a string, this means that you want to connect to socket.io "message" type
Request n°3
GET
url: /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=sessionIdFromRequest1
Namespace connection approval : This will return if the connection is successful or if there is an error, here is when the socket.io server authorizes your connection if you need a token.
Request n°4
POST
url: /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=sessionIdFromRequest1
post body: 42[event,data]
For example 42["notifications","Hi, Im a notification"] and is equivalent to socket.emit(event,data)
Emit message to server: Send your message to the socket.io server.
Here is a BASIC example using Symfony 5.2 and HttpClientInterface:
<?php
// install dependencies before: composer require symfony/http-client
use Symfony\Component\HttpClient\CurlHttpClient;
include('vendor/autoload.php');
$client = new CurlHttpClient();
sendToSocket($client);
function sendToSocket(HttpClientInterface $client)
{
$first = $client->request('GET', 'http://localhost:3000/socket.io/?EIO=4&transport=polling&t=N8hyd6w');
$res = ltrim($first->getContent(), '0');
$res = json_decode($res, true);
$sid = $res['sid'];
$second = $client->request('POST', 'http://localhost:3000/socket.io/?EIO=4&transport=polling&sid='.$sid, [
'body' => '40'
]);
$third = $client->request('GET', 'http://localhost:3000/socket.io/?EIO=4&transport=polling&sid='.$sid);
$fourth = $client->request('POST', 'http://localhost:3000/socket.io/?EIO=4&transport=polling&sid='.$sid, [
'body' => '42["notifications","Hi, Im a notification"]'
]);
}
As you can see, is very easy, and you dont need the troubling "copy-pasted" libraries out there. I said "copy-pasted" because all use the same code to open de socket and send the information, but no one is compatible with socket.io V3.
Here is an image, proving that the given code works as January 4 2021 with php 7.4, symfony 5.2 and socket.io V3.
This is my test server in node
// Install dependencies before: npm i express socket.io
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});
io.on('connection', function (socket) {
console.log("New Connection with transport", socket.conn.transport.name);
socket.on('notifications', function (data) {
console.log(data);
});
});
http.listen(3000, () => {
console.log('Server started port 3000');
});
I need to say that this solution works excellent if you want to send "one direction" messages to your socket.io server, like a new notification or whatever that doesn't need a permanent connection, is just "one shot" and nothing else.
Happy coding and greetings from Mexico.
Here is another example:
First column is Postman making a request to the php server, simulating a server side event, like a new question created. In the response are the dumps of the response body from the 4 requests that you need to make.
Second column is the socket.IO node server running on port 3000
And the last column is the chrome console, simulating a user connected to the socket.IO server via websocket looking for notifications in 'questions' event.
I am working on a little project of mine and have built a UDP scraper that uses sockets to return data about a specific sha1 hash.
It works but is incredibly slow and wondered if any one knows how I could speed it up or improve the existing code.
The code is below;
// SCRAPE UDP
private function scrapeUDP($tracker, $hash) {
// GET TRACKER DETAILS
preg_match('%udp://([^:/]*)(?::([0-9]*))?(?:/)?%i', $tracker, $info);
// GENERATE TRANSACTION ID
$transID = mt_rand(0, 65535);
// PACKED TRANSACTION ID
$packedTransID = pack('N', $transID);
// ATTEMPT TO CREATE A SOCKET
if(!$socket = #fsockopen('udp://' . $info[1], $info[2], $errno, $errstr, 2)) {
return;
}
// SET STREAM TIMEOUT
stream_set_timeout($socket, 2);
// CONNECTION ID
$connID = "\x00\x00\x04\x17\x27\x10\x19\x80";
// BUILD CONNECTION REQUEST PACKET
$packet = $connID . pack('N', 0) . $packedTransID;
// SEND PACKET
fwrite($socket, $packet);
// CONNECTION RESPONSE
$response = fread($socket, 16);
// CHECK CONNECTION RESPONSE LENGTH
if(strlen($response) < 16) {
return;
}
// UNPACK CONNECTION RESPONSE
$returnData = unpack('Naction/NtransID', $response);
// CHECK CONNECTION RESPONSE DATA
if($returnData['action'] != 0 || $returnData['transID'] != $transID) {
return;
}
// GET CONNECTION ID
$connID = substr($response, 8, 8);
// BUILD SCRAPE PACKET
$packet = $connID . pack('N', 2) . $packedTransID . $hash;
// SEND SCRAPE PACKET
fwrite($socket, $packet);
// SCRAPE RESPONSE
$response = fread($socket, 20);
// CHECK SCRAPE RESPONSE LENGTH
if(strlen($response) < 20) {
return;
}
// UNPACK SCRAPE RESPONSE
$returnData = unpack('Naction/NtransID', $response);
// CHECK SCRAPE RESPONSE DATA
if($returnData['action'] != 2 || $returnData['transID'] != $transID) {
return;
}
// UNPACK SCRAPE INFORMATION
$returnData = unpack('Nseeders/Ncompleted/Nleechers', substr($response, 8, 12));
// RETURN TRACKER INFORMATION
return array('seeders' => $returnData['seeders'], 'leechers' => $returnData['leechers'],);
}
It is my first time I have ever created anything to do with sockets or UDP so forgive me if it is a mess!
Thanks...
You have to make parallel request using socket_select() and non-blocking sockets or forks, because you are spending a lot of time in waiting for the response. Additionally, it may be better to use low-level functions like socket_read() or similar to control connection and data transmission better.
I have a XML RPC server running with Python.
It is implemented as an instance of the SimpleXMLRPCServer class.
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
class MyClass:
def getGeneExtraInfo(self,genome,infoType,elements):
print 'DEBUG:\ngenome: %s\ninfoType: %s, elements %s' % (genome,infoType,elements)
return 'A' * 10000
csfServer = MyClass()
server = SimpleXMLRPCServer((serverHost, serverPort), SimpleXMLRPCRequestHandler)
server.register_instance(csfServer)
server.serve_forever()
The csfServer has the method def getGeneExtraInfo(self,genome,infoType,elements) that returns a long string, lets consider, just for sake of simplicity, that is returs 10000 repetitions of "A".
I access this web service through PHP by this code:
function sendRequest($host, $url, $request, $port = 80) {
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
return FALSE;
}
$address = gethostbyname($host);
if (!socket_connect ($socket, $address, $port)) {
echo socket_strerror(socket_last_error());
return FALSE;
}
$httpQuery = "POST ". $url ." HTTP/1.0\r\n";
$httpQuery .= "User-Agent: xmlrpc\r\n";
$httpQuery .= "Host: ". $host ."\r\n";
$httpQuery .= "Content-Type: text/xml\r\n";
$httpQuery .= "Content-Length: ". strlen($request) ."\r\n\r\n";
$httpQuery .= $request ."\r\n";
if (!socket_send($socket, $httpQuery , strlen($httpQuery), 0)) {
echo socket_strerror(socket_last_error());
return FALSE;
}
$xmlResponse = "";
$buff = "";
while ($bytes = socket_recv($socket, $buff, 1024, MSG_WAITALL) > 0) {
$xmlResponse .= $buff;
}
// Just for debugging
echo "socket_recv() failed; reason: " . socket_strerror(socket_last_error($socket)) . "\n";
socket_close($socket);
return $xmlResponse;
}
The $request variable is build:
$xmlrpc_output_options = array(
"output_type" => "xml",
"verbosity" => "no_white_space",
"escaping" => array("markup", "non-ascii", "non-print"),
"version" => "xmlrpc",
"encoding" => "UTF-8");
$xmlRequest = xmlrpc_encode_request('getGeneExtraInfo', array($genome,$infoType,$elements), $xmlrpc_output_options);
(It is possible to see the built request inside the following C and Python code)
The php client and server works properly when the server is running with python 2.4, but when the server is executed with python 2.5 or 2.6, sometimes (50% of the times), the data comes incomplete and with 'Connection reset by peer' error.
To verify if the problem is with Python or PHP, I wrote two clients, one in C and other in Python. Both uses sockets and mainly how the PHP code works. The "request" content was copied from the PHP output, it means that is exactly the request for the PHP, C, and Python.
The C code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char* hostname= "wks-13-15";
int portno = 56572;
char buffer[1024];
char request[] = "POST / HTTP/1.0\r\nUser-Agent: xmlrpc\r\nHost: wks-13-15\r\nContent-Type: text/xml\r\nContent-Length: 4479\r\n\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?><methodCall><methodName>getGeneExtraInfo</methodName><params><param><value><string>hg19</string></value></param><param><value><string>GO</string></value></param><param><value><array><data><value><string>GO:0044428</string></value><value><string>GO:0044422</string></value><value><string>GO:0044425</string></value><value><string>GO:0044424</string></value><value><string>GO:0043412</string></value><value><string>GO:0006464</string></value><value><string>GO:0009889</string></value><value><string>GO:0003824</string></value><value><string>GO:0016020</string></value><value><string>GO:0016021</string></value><value><string>GO:0048522</string></value><value><string>GO:0048523</string></value><value><string>GO:0090304</string></value><value><string>GO:0019538</string></value><value><string>GO:0051171</string></value><value><string>GO:0001882</string></value><value><string>GO:0001883</string></value><value><string>GO:0080090</string></value><value><string>GO:0042221</string></value><value><string>GO:0048869</string></value><value><string>GO:0019222</string></value><value><string>GO:0005488</string></value><value><string>GO:0005886</string></value><value><string>GO:0005524</string></value><value><string>GO:0031090</string></value><value><string>GO:0050896</string></value><value><string>GO:0010556</string></value><value><string>GO:0010468</string></value><value><string>GO:0016740</string></value><value><string>GO:0003677</string></value><value><string>GO:2000112</string></value><value><string>GO:0005622</string></value><value><string>GO:0019219</string></value><value><string>GO:0006139</string></value><value><string>GO:0032502</string></value><value><string>GO:0032501</string></value><value><string>GO:0050794</string></value><value><string>GO:0009058</string></value><value><string>GO:0032991</string></value><value><string>GO:0044249</string></value><value><string>GO:0044260</string></value><value><string>GO:0044267</string></value><value><string>GO:0035639</string></value><value><string>GO:0009987</string></value><value><string>GO:0044464</string></value><value><string>GO:0051252</string></value><value><string>GO:0043170</string></value><value><string>GO:0005634</string></value><value><string>GO:0005737</string></value><value><string>GO:0050789</string></value><value><string>GO:0031326</string></value><value><string>GO:0051716</string></value><value><string>GO:0016787</string></value><value><string>GO:0031323</string></value><value><string>GO:0006810</string></value><value><string>GO:0048856</string></value><value><string>GO:0065007</string></value><value><string>GO:0043227</string></value><value><string>GO:0043167</string></value><value><string>GO:0044459</string></value><value><string>GO:0043169</string></value><value><string>GO:0008150</string></value><value><string>GO:0008152</string></value><value><string>GO:0006355</string></value><value><string>GO:0005575</string></value><value><string>GO:0046914</string></value><value><string>GO:0003674</string></value><value><string>GO:0006807</string></value><value><string>GO:0003676</string></value><value><string>GO:0044446</string></value><value><string>GO:0044444</string></value><value><string>GO:0051234</string></value><value><string>GO:0032555</string></value><value><string>GO:0043228</string></value><value><string>GO:0043229</string></value><value><string>GO:0043226</string></value><value><string>GO:0045449</string></value><value><string>GO:0032559</string></value><value><string>GO:0031224</string></value><value><string>GO:0017076</string></value><value><string>GO:0071842</string></value><value><string>GO:0071841</string></value><value><string>GO:0071840</string></value><value><string>GO:0060255</string></value><value><string>GO:0016043</string></value><value><string>GO:0034641</string></value><value><string>GO:0008270</string></value><value><string>GO:0000166</string></value><value><string>GO:0046872</string></value><value><string>GO:0044237</string></value><value><string>GO:0044238</string></value><value><string>GO:0043234</string></value><value><string>GO:0043231</string></value><value><string>GO:0043232</string></value><value><string>GO:0032553</string></value><value><string>GO:0005515</string></value><value><string>GO:0007165</string></value><value><string>GO:0048519</string></value><value><string>GO:0048518</string></value><value><string>GO:0030554</string></value></data></array></value></param></params></methodCall>";
fprintf(stderr, "%s\n", request);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(hostname);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
fprintf(stderr, "%d\n", strlen(request));
n = write(sockfd,request,strlen(request));
if (n < 0)
error("ERROR writing to socket");
fprintf(stderr, "%d\n", n);
bzero(buffer,1024);
while (read(sockfd,buffer,1023) > 0) {
printf("%s",buffer);
bzero(buffer,1024);
}
if (n < 0)
error("ERROR reading from socket");
close(sockfd);
return 0;
}
The python code:
import socket
request = """POST / HTTP/1.0
User-Agent: xmlrpc
Host: wks-13-15
Content-Type: text/xml
Content-Length: 4479
<?xml version="1.0" encoding="UTF-8"?><methodCall><methodName>getGeneExtraInfo</methodName><params><param><value><string>hg19</string></value></param><param><value><string>GO</string></value></param><param><value><array><data><value><string>GO:0044428</string></value><value><string>GO:0044422</string></value><value><string>GO:0044425</string></value><value><string>GO:0044424</string></value><value><string>GO:0043412</string></value><value><string>GO:0006464</string></value><value><string>GO:0009889</string></value><value><string>GO:0003824</string></value><value><string>GO:0016020</string></value><value><string>GO:0016021</string></value><value><string>GO:0048522</string></value><value><string>GO:0048523</string></value><value><string>GO:0090304</string></value><value><string>GO:0019538</string></value><value><string>GO:0051171</string></value><value><string>GO:0001882</string></value><value><string>GO:0001883</string></value><value><string>GO:0080090</string></value><value><string>GO:0042221</string></value><value><string>GO:0048869</string></value><value><string>GO:0019222</string></value><value><string>GO:0005488</string></value><value><string>GO:0005886</string></value><value><string>GO:0005524</string></value><value><string>GO:0031090</string></value><value><string>GO:0050896</string></value><value><string>GO:0010556</string></value><value><string>GO:0010468</string></value><value><string>GO:0016740</string></value><value><string>GO:0003677</string></value><value><string>GO:2000112</string></value><value><string>GO:0005622</string></value><value><string>GO:0019219</string></value><value><string>GO:0006139</string></value><value><string>GO:0032502</string></value><value><string>GO:0032501</string></value><value><string>GO:0050794</string></value><value><string>GO:0009058</string></value><value><string>GO:0032991</string></value><value><string>GO:0044249</string></value><value><string>GO:0044260</string></value><value><string>GO:0044267</string></value><value><string>GO:0035639</string></value><value><string>GO:0009987</string></value><value><string>GO:0044464</string></value><value><string>GO:0051252</string></value><value><string>GO:0043170</string></value><value><string>GO:0005634</string></value><value><string>GO:0005737</string></value><value><string>GO:0050789</string></value><value><string>GO:0031326</string></value><value><string>GO:0051716</string></value><value><string>GO:0016787</string></value><value><string>GO:0031323</string></value><value><string>GO:0006810</string></value><value><string>GO:0048856</string></value><value><string>GO:0065007</string></value><value><string>GO:0043227</string></value><value><string>GO:0043167</string></value><value><string>GO:0044459</string></value><value><string>GO:0043169</string></value><value><string>GO:0008150</string></value><value><string>GO:0008152</string></value><value><string>GO:0006355</string></value><value><string>GO:0005575</string></value><value><string>GO:0046914</string></value><value><string>GO:0003674</string></value><value><string>GO:0006807</string></value><value><string>GO:0003676</string></value><value><string>GO:0044446</string></value><value><string>GO:0044444</string></value><value><string>GO:0051234</string></value><value><string>GO:0032555</string></value><value><string>GO:0043228</string></value><value><string>GO:0043229</string></value><value><string>GO:0043226</string></value><value><string>GO:0045449</string></value><value><string>GO:0032559</string></value><value><string>GO:0031224</string></value><value><string>GO:0017076</string></value><value><string>GO:0071842</string></value><value><string>GO:0071841</string></value><value><string>GO:0071840</string></value><value><string>GO:0060255</string></value><value><string>GO:0016043</string></value><value><string>GO:0034641</string></value><value><string>GO:0008270</string></value><value><string>GO:0000166</string></value><value><string>GO:0046872</string></value><value><string>GO:0044237</string></value><value><string>GO:0044238</string></value><value><string>GO:0043234</string></value><value><string>GO:0043231</string></value><value><string>GO:0043232</string></value><value><string>GO:0032553</string></value><value><string>GO:0005515</string></value><value><string>GO:0007165</string></value><value><string>GO:0048519</string></value><value><string>GO:0048518</string></value><value><string>GO:0030554</string></value></data></array></value></param></params></methodCall>"""
HOST = "wks-13-15"
PORT = 56572
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(request)
while 1:
data = s.recv(1024)
print data
if not data: break
s.close()
Both programs work and receives the entire response data.
I already tried to change the encoding, change how the data is read by the PHP, but the incomplete data and Connection reset by peer problem persist.
My questions: (feel free to answer any of them :-) )
Why the C and Python programs works, while PHP sometimes doesn't?
Why sometimes PHP code works, and others doesn't?
Why with the server running on a python 2.4, the PHP client code works, and with python 2.5 and 2.6 doesn't?
How can I solve it? Suggestions are welcome.
I use the xml_rpc class, I am not sure which version of PHP this started with but it works for me. It even will encode your request from an array, but if you already have your XML for the request I would do this:
PHP
function sendRequest($host, $url, $request, $port = 80) {
//create the context to send to the xmlrpc server
$context = stream_context_create(array('http' => array(
'method' => "POST",
'header' => "Content-Type: text/xml\r\nUser-Agent: PHPRPC/1.0\r\n",
'content' => $request
)));
//i am not sure how to get the url, normally something like http://server/api/xml
$server = "http://$host:$port"; //?
//store the response
$file = file_get_contents($server, false, $context);
//decode the response to xml
$return xmlrpc_decode($file);
}
Hi I have a running socket server written with PHP.
The server is listening for connections.. any idea how my client(written in javascript) is going to connect to the server and send data to it?
PS: I only know how to connect a php client to the socket server but unsure how to connect a javascript client.
Thanks all for your time.
I use standard WebSocket API for client.
And core PHP socket for server side.
know, send and received data use a header on the browser with websocket. But the code PHP socket, send and received without header and just send plain data.
So we need to simulate header on the socketing server side.
For learning and know how do it, I write this clear sample code, With this code you can send a phrase to server and receive reverse phrase that in client.
server.php
<?php
//Code by: Nabi KAZ <www.nabi.ir>
// set some variables
$host = "127.0.0.1";
$port = 5353;
// don't timeout!
set_time_limit(0);
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0)or die("Could not create socket\n");
// bind socket to port
$result = socket_bind($socket, $host, $port)or die("Could not bind to socket\n");
// start listening for connections
$result = socket_listen($socket, 20)or die("Could not set up socket listener\n");
$flag_handshake = false;
$client = null;
do {
if (!$client) {
// accept incoming connections
// client another socket to handle communication
$client = socket_accept($socket)or die("Could not accept incoming connection\n");
}
$bytes = #socket_recv($client, $data, 2048, 0);
if ($flag_handshake == false) {
if ((int)$bytes == 0)
continue;
//print("Handshaking headers from client: ".$data."\n");
if (handshake($client, $data, $socket)) {
$flag_handshake = true;
}
}
elseif($flag_handshake == true) {
if ($data != "") {
$decoded_data = unmask($data);
print("< ".$decoded_data."\n");
$response = strrev($decoded_data);
socket_write($client, encode($response));
print("> ".$response."\n");
socket_close($client);
$client = null;
$flag_handshake = false;
}
}
} while (true);
// close sockets
socket_close($client);
socket_close($socket);
function handshake($client, $headers, $socket) {
if (preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $headers, $match))
$version = $match[1];
else {
print("The client doesn't support WebSocket");
return false;
}
if ($version == 13) {
// Extract header variables
if (preg_match("/GET (.*) HTTP/", $headers, $match))
$root = $match[1];
if (preg_match("/Host: (.*)\r\n/", $headers, $match))
$host = $match[1];
if (preg_match("/Origin: (.*)\r\n/", $headers, $match))
$origin = $match[1];
if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $headers, $match))
$key = $match[1];
$acceptKey = $key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
$acceptKey = base64_encode(sha1($acceptKey, true));
$upgrade = "HTTP/1.1 101 Switching Protocols\r\n".
"Upgrade: websocket\r\n".
"Connection: Upgrade\r\n".
"Sec-WebSocket-Accept: $acceptKey".
"\r\n\r\n";
socket_write($client, $upgrade);
return true;
} else {
print("WebSocket version 13 required (the client supports version {$version})");
return false;
}
}
function unmask($payload) {
$length = ord($payload[1]) & 127;
if ($length == 126) {
$masks = substr($payload, 4, 4);
$data = substr($payload, 8);
}
elseif($length == 127) {
$masks = substr($payload, 10, 4);
$data = substr($payload, 14);
}
else {
$masks = substr($payload, 2, 4);
$data = substr($payload, 6);
}
$text = '';
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i % 4];
}
return $text;
}
function encode($text) {
// 0x1 text frame (FIN + opcode)
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if ($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)$header = pack('CCS', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCN', $b1, 127, $length);
return $header.$text;
}
client.htm
<html>
<script>
//Code by: Nabi KAZ <www.nabi.ir>
var socket = new WebSocket('ws://localhost:5353');
// Open the socket
socket.onopen = function(event) {
var msg = 'I am the client.';
console.log('> ' + msg);
// Send an initial message
socket.send(msg);
// Listen for messages
socket.onmessage = function(event) {
console.log('< ' + event.data);
};
// Listen for socket closes
socket.onclose = function(event) {
console.log('Client notified socket has closed', event);
};
// To close the socket....
//socket.close()
};
</script>
<body>
<p>Please check the console log of your browser.</p>
</body>
</html>
Manual: first run php server.php on CLI and then open http://localhost/client.htm on browser.
You can see result:
http://localhost/client.htm
> I am the client.
< .tneilc eht ma I
php server.php
< I am the client.
> .tneilc eht ma I
Be careful it's just a sample code for test send and receive data, And it is not useful for executive work.
I suggest you use these projects:
https://github.com/ghedipunk/PHP-Websockets
https://github.com/esromneb/phpwebsocket
https://github.com/acbrandao/PHP/tree/master/ws
https://github.com/srchea/PHP-Push-WebSocket/
http://socketo.me/
And also I suggest you these articles for more details:
http://www.abrandao.com/2013/06/websockets-html5-php/
http://cuelogic.com/blog/php-and-html5-websocket-server-and-client-communication/
http://srchea.com/build-a-real-time-application-using-html5-websockets
Answering an old question in case people find it as I did via Google.
Nowadays nearly all contemporary browsers support the WebSocket Javascript API. Via WS it's possible for client JS in the browser to open full duplex sockets to severs written in PHP or other languages. The server must implement the WS protocol, but there are WS libraries now for PHP, Java, and other languages.
At this moment of writing, WS implementations still seem like a bit of a moving target, but, I'm currently working with WS/JS browser clients communicating with a WS/Java server and it does seem to be working.
Suggest Googling for WS implementations in your server language of choice.
Hope this helps!
I'm not aware of anything that provides arbitrary socket capabilities for JS. There is limited support for Web Sockets (which I think will require you to modify the server to conform to the space). Failing that, simple XHR might meet your needs (which would require that you modify the server to act as a web service). If the service runs on a different origin to the page, then you will need to use CORS or use a work around such as JSONP.
Try this:
http://code.google.com/p/phpwebsocket/
Shortly saying - you can't do that - it would be a security breach to let client side code open socket connections.
However, you could simulate that - send your data to another PHP page as an AJAX request, then make that PHP page communicate through the socket.
Update 2017:
In the mean time, websockets became a thing. Please note that the websocket protocol is a different thing than generic networking sockets