Как отправить с php client на websoket данные?

Добрый день.
Собственно такая проблема, есть веб сокет на Ratchet к нему уже подрублен браузер который прекрасно с ним соединяется( вообщем проблем с web socket - браузер нет ), проблема возникла тогда когда я начал подключать к сокету php скрипт, сам скрипт к сокету подрубается и может от него получать данные, но вот обратно отправлять их на сокет он не может не как. Пробовал через fwrite и stream_socket_sendto, оба варианта не дали не какого результата.

код для подключения к сокету:
$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);
        }


Код самого сокет сервера на ratchet я приводить не буду он стандартный, все как в доке описано.

PS помогите разобраться, а то уже вторые сутки бьюсь все не как не могу понять что я делаю не так, ведь в теории если приведенный мною скрипт может получать данные с сокета, то 100% он должен их и как то отправлять.
  • Вопрос задан
  • 1667 просмотров
Решения вопроса 1
@rdbnko Автор вопроса
Вообщем если у кого возник такая проблема(ответ нашел на 4 странице в гугле в конце), то нужно сделать следующее(данный вариан решения проблемы подходит не только для 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;
    }
}


PS Ссылка на оригинал
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Slavenin999
@Slavenin999
программист php/erlang/elixir/js
я делал как-то так для создания сокета:
ob_implicit_flush();

			if( ($sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP )) === false )
			{
				self::fault(self::ERROR_SCR, $sock, __LINE__);
				exit();
			}

			socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);

			self::log("сервер: сокет создан\n");

			if( socket_bind( $sock, $_SERVER['HTTP_HOST'], self::$port ) === false )
			{
				self::fault(self::ERROR_SBND, $sock, __LINE__);
				exit();
			}

			self::log("сервер: сокет привязан\n");

			if( socket_listen( $sock, 2 ) === false )
			{
				self::fault(self::ERROR_SLI, $sock, __LINE__);
				exit();
			}

			self::log("сервер: сокет слушается\n");

			session_write_close();
			socket_set_nonblock($sock);


а для подключения:
private
			function getAcceptMsg($input)
		{
			preg_match("/Sec-WebSocket-Key: (.*);/uU", $input, $temp );
			$key_acp = $temp[ 1 ];
			$key_acp = base64_encode( sha1( $key_acp . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true ) );
			$msg = "HTTP/1.1 101 Swithing Protocols\r\n";
			$msg .= "Upgrade: websocket\r\n";
			$msg .= "Connection: Upgrade\r\n";
			$msg .= "Sec-Websocket-Accept: {$key_acp}\r\n\r\n";

			return $msg;
		}


//отвечаем браузеру
						$msg = $this->getAcceptMsg($input);
						socket_write( $msgsock, $msg, strlen( $msg ) );
						socket_set_nonblock($msgsock);
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы