Good day. Actually such a problem: there is a web socket on Ratchet, a browser is already hooked up to it which connects to it perfectly (in general there are no problems with a web socket), the problem arose when I started to connect a script to the php socket, the script to the socket is trimmed and he can receive data from him, but he can’t send them back to the socket. I tried through fwrite and stream_socket_sendto , both options did not give any result.

Socket connection code:

 $socket = stream_socket_client('tcp://localhost:8080', $errorNumber, $errorString, 1); 

stream_set_blocking ($ socket, 0);

  if (!$socket) { echo "{$errorString} ({$errorNumber})<br />\n"; } else { $header = "GET / HTTP/1.1\r\n" . "Host: localhost\r\n" . "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" . "Sec-WebSocket-Key: tQXaRIOk4sOhgoq7SBs43g==\r\n" . "Sec-WebSocket-Version: 13\r\n\r\n"; fwrite($socket, $header); while (!feof($socket)) { $context = fgets($socket, 1024); echo($context); } fclose($socket); } 

The code of the server socket itself on ratchet I will not give it standard, everything is described in the dock.

PS help me figure it out, but for the second day I’m fighting, I don’t understand how I’m doing wrong, because in theory, if the script I’ve given can get data from a socket, then it should 100% send it and send it.

  • Why don't you want to use the packagist.org/packages/cboden/ratchet native package? Why are these bikes? - Zhukov Roman
  • The problem is that, as I understood from reading the docks there, ZeroMQ is needed for this, which I not only do not need, but will also use other things instead of it. True, my English is not very good, so I could simply overlook or understand something not so. - user2382768
  • For the link to the doc I will be grateful - user2382768
  • People help, I don’t know what’s wrong with him, everything seems to be right, but it’sn’t working, anyone can explain how to do it, surely there’s an error somewhere in logic, but where I don’t know, they write on one of the forums, that it is necessary to keep the connection constantly open, so that this thing would work, but it is already open all the time, and there is no sense from it - user2382768

2 answers 2

In general, if anyone has such a problem (the answer found on page 4 in Google at the end), then you need to do the following (this solution is not only suitable for symfony):

 <?php namespace Calc\ApiBundle\Command\Sockets; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class HttpClientCommand extends ContainerAwareCommand { protected function configure() { $this->setName('server:run') ->setDescription('Š—Š°ŠæŃƒŃŠŗŠ°ŠµŠ¼ сокет.'); } protected function execute(InputInterface $input, OutputInterface $output) { $socket = stream_socket_client('tcp://localhost:8080', $errorNumber, $errorString, 1); if (!$socket) { echo "{$errorString} ({$errorNumber})<br />\n"; } else { $data = "first message"; $head = "GET / HTTP/1.1\r\n" . "Host: localhost\r\n" . "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" . "Sec-WebSocket-Key: tQXaRIOk4sOhqwe7SBs43g==\r\n" . "Sec-WebSocket-Version: 13\r\n" . "Content-Length: ".strlen($data)."\r\n"."\r\n"; fwrite($socket, $head); $headers = fread($socket, 2000); echo $headers; fwrite($socket, $this->hybi10Encode($data)); $wsdata = fread($socket, 2000); var_dump($this->hybi10Decode($wsdata)); fclose($socket); /*fwrite($socket, $header); while (!feof($socket)) { $context = fgets($socket, 1024); echo($context); } fclose($socket);*/ } } private function hybi10Decode($data) { $bytes = $data; $dataLength = ''; $mask = ''; $coded_data = ''; $decodedData = ''; $secondByte = sprintf('%08b', ord($bytes[1])); $masked = ($secondByte[0] == '1') ? true : false; $dataLength = ($masked === true) ? ord($bytes[1]) & 127 : ord($bytes[1]); if($masked === true) { if($dataLength === 126) { $mask = substr($bytes, 4, 4); $coded_data = substr($bytes, 8); } elseif($dataLength === 127) { $mask = substr($bytes, 10, 4); $coded_data = substr($bytes, 14); } else { $mask = substr($bytes, 2, 4); $coded_data = substr($bytes, 6); } for($i = 0; $i < strlen($coded_data); $i++) { $decodedData .= $coded_data[$i] ^ $mask[$i % 4]; } } else { if($dataLength === 126) { $decodedData = substr($bytes, 4); } elseif($dataLength === 127) { $decodedData = substr($bytes, 10); } else { $decodedData = substr($bytes, 2); } } return $decodedData; } private function hybi10Encode($payload, $type = 'text', $masked = true) { $frameHead = array(); $frame = ''; $payloadLength = strlen($payload); switch ($type) { case 'text': // first byte indicates FIN, Text-Frame (10000001): $frameHead[0] = 129; break; case 'close': // first byte indicates FIN, Close Frame(10001000): $frameHead[0] = 136; break; case 'ping': // first byte indicates FIN, Ping frame (10001001): $frameHead[0] = 137; break; case 'pong': // first byte indicates FIN, Pong frame (10001010): $frameHead[0] = 138; break; } // set mask and payload length (using 1, 3 or 9 bytes) 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]); } // most significant bit MUST be 0 (close connection if frame too big) 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; } // convert frame-head to string: foreach (array_keys($frameHead) as $i) { $frameHead[$i] = chr($frameHead[$i]); } if ($masked === true) { // generate a random mask: $mask = array(); for ($i = 0; $i < 4; $i++) { $mask[$i] = chr(rand(0, 255)); } $frameHead = array_merge($frameHead, $mask); } $frame = implode('', $frameHead); // append payload to frame: for ($i = 0; $i < $payloadLength; $i++) { $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i]; } return $frame; } } 
  • link to the original Original - user2382768

Why sockets? Would you like to use the same cURL, which is much faster and safer than sockets and file_get_contents ().

cURL

Upd 1: On the week, I saw just a smart socket library - Socket.io.

Write the server part on Node.js, if it can be done on your hosting, etc., and connect the reception on sockets by keys to Socket.io.

Today I will do a test API. An example I will lay out on githabe.

  • one
    Sockets are needed just to reduce the load from apiha, now the front is engaged in simply bombarding apiha through Ajax, in fact, to remove this horror and we need sockets. - user2382768
  • At the same time, sockets are needed only to connect the front with apiha, through a permanent connection, since what it gives to apiha is the data that it collects from different resources, just through cURL, there are a lot of data somewhere 40 pieces, all 40 from different resources, as a result, some of them are requested through a proxy, so some people can go in a second, others can come only after 1 minute, so that the user doesn’t sit and look at the loading bar, you just need a socket that as soon as data appears give to the front, getting them in my eyes ed from different background processes. - user2382768
  • Really no one can help. In general, what would be quite clear, I want to achieve the following: there is a C (client) it makes a request for WS (socket) the socket sends data to the daemon (D) the demon puts the received data in the queue (G) further the process that listens to the queue processes everything This business and back to WS Well, and WS gives already C - user2382768
  • Actually the only problem is how to transfer data to the socket and that's it - user2382768
  • All is easier the socket rises on python / nodejs, then through redis pub / sub - user2382768