/** * Send a message to WebSocket clients (use port + 1 for SSL connections) */ public static function send($type, $msg, $to = false) { $proto = self::$ssl ? 'wss' : 'ws'; $port = self::$ssl ? self::$port + 1 : self::$port; $ws = new WebSocketClient("{$proto}://localhost:" . self::$port); $ws->send(json_encode(array('type' => $type, 'from' => self::$clientID, 'msg' => $msg, 'to' => $to))); $ws->close(); }
private function send($msg) { $msg = WebSocketClient::draft10Encode($msg, 'text', true); if (!fwrite($this->sock, $msg)) { throw new \Exception('Socket write error! ' . PHP_EOL); } }
private function registerClient() { if (($client = @stream_socket_accept($this->handle)) !== false) { $clientHandle = new WebSocketClient($client); $this->log('Start session %s:%d', self::LOG_INFO, $clientHandle->address, $clientHandle->port); $header = array(); $state = false; $request = $clientHandle->read(); foreach (explode("\n", trim($request)) as $line) { if ($state === false) { $header[] = trim($line); $state = true; } else { $data = explode(':', $line); $header[strtolower($data[0])] = trim(implode(':', array_slice($data, 1))); } } if (isset($header[0]) === false || preg_match('/^GET (.*?) HTTP/i', $header[0], $match) === 0) { $this->sendHandShakeError($clientHandle, 400); return false; } $resource = parse_url($match[1]); if (isset($resource['path']) === false) { $this->sendHandShakeError($clientHandle, 400); return false; } $clientHandle->resource = $resource === '/' ? '/' : substr($resource['path'], 1); if (isset($resource['query']) === true) { parse_str($resource['query'], $clientHandle->resourceQuery); } else { $clientHandle->resourceQuery = array(); } if ($clientHandle->resource !== '/' && isset($this->maxResourceClients[$clientHandle->resource]) === false) { $this->sendHandShakeError($clientHandle, 400); return false; } $clientHandle->version = isset($header['sec-websocket-version']) === false ? 0 : (int) $header['sec-websocket-version']; if (isset($header['sec-websocket-key']) === true) { $clientHandle->rfc = true; if ($this->checkOrigin !== false) { if (isset($header['origin']) === false && isset($header['sec-websocket-origin']) === false) { $this->sendHandShakeError($client, 400); return false; } $check = parse_url(isset($header['host']) === true ? $header['host'] : (isset($header['origin']) === true ? $header['origin'] : $header['sec-websocket-origin'])); if (isset($check['host']) === false || in_array($check['host'], $this->checkOrigin) === false || ($this->port !== 80 && $this->port !== 443 && isset($check['port']) === false || $this->port !== $check['port'])) { $this->sendHandShakeError($client, 400); return false; } } // send handshake $handshake = "HTTP/1.1 101 Switching Protocols\r\n"; $handshake .= "Upgrade: websocket\r\n"; $handshake .= "Connection: Upgrade\r\n"; $handshake .= "Sec-WebSocket-Accept: " . base64_encode(sha1($header['sec-websocket-key'] . self::GUID, true)) . "\r\n"; $handshake .= "\r\n"; $clientHandle->write($handshake); } else { if (isset($header['sec-websocket-key1'], $header['sec-websocket-key2'], $header['host']) === true) { $clientHandle->rfc = false; if (isset($header['origin']) === false && isset($header['sec-websocket-origin']) === false) { $this->sendHandShakeError($clientHandle, 400); return false; } $origin = isset($header['origin']) === true ? $header['origin'] : $header['sec-websocket-origin']; if ($this->checkOrigin !== false) { $check = parse_url(isset($header['host']) === true ? $header['host'] : (isset($header['origin']) === true ? $header['origin'] : $header['sec-websocket-origin'])); if (isset($check['host']) === false || in_array($check['host'], $this->checkOrigin) === false || ($this->port !== 80 && $this->port !== 443 && isset($check['port']) === false || $this->port !== $check['port'])) { $this->sendHandShakeError($client, 400); return false; } } // 許可キー $accept = ''; // 固定の最大サイズ $maxDigitSize = 10; // get spaces for ($i = 0; $i < 2; $i++) { $spaces = 0; $digit = ''; $char = $header['sec-websocket-key' . ($i + 1)]; for ($j = 0, $size = strlen($char); $j < $size; $j++) { if (substr_count('0123456789', $char[$j]) > 0) { $digit .= $char[$j]; } else { if ($char[$j] === ' ') { $spaces++; } } } if ($spaces === 0 || strlen($digit) > $maxDigitSize) { // zero... $this->sendHandShakeError($clientHandle, 400); return false; } // 11桁以上いかないので、floatで計算しても問題ない。 $accept .= pack('N', (int) ((double) $digit / (double) $spaces)); } $handshake = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"; $handshake .= "Upgrade: WebSocket\r\n"; $handshake .= "Connection: Upgrade\r\n"; $handshake .= "Sec-WebSocket-Origin: " . $origin . "\r\n"; $handshake .= "Sec-WebSocket-Location: ws://" . $header['host'] . "/" . ($clientHandle->resource !== '/' ? $clientHandle->resource : '') . "\r\n"; $handshake .= "\r\n"; // find body from request $body = ''; for ($i = 0, $size = strlen($request); $i < $size; $i++) { if ($request[$i] === "\r" && isset($request[$i + 1], $request[$i + 2], $request[$i + 3]) === true && $request[$i + 1] === "\n" && $request[$i + 2] === "\r" && $request[$i + 3] === "\n") { $i += 4; break; } else { if ($request[$i] === "\n" && isset($request[$i + 1]) === true && $request[$i + 1] === "\n") { $i += 2; break; } } } $body = substr($request, $i); // attack code? if (strlen($body) !== 8) { $this->sendHandShakeError($clientHandle, 400); return false; } // to binary $handshake .= md5($accept . $body, true); $clientHandle->write($handshake); } else { $this->sendHandShakeError($clientHandle, 400); return false; } } $clientHandle->id = sha1($clientHandle->timestamp . $clientHandle->address . $clientHandle->port . $clientHandle->resource . $clientHandle->version); if ($this->maxResourceClients[$clientHandle->resource]['size'] > -1 && $this->maxResourceClients[$clientHandle->resource]['connections'] + 1 > $this->maxResourceClients[$clientHandle->resource]['size']) { $this->sendHandShakeError($clientHandle, 503); return false; } // 接続数の増加 $this->maxResourceClients[$clientHandle->resource]['connections']++; $this->clients[] = $clientHandle; // connect イベント $this->triggerEvent('connect', $clientHandle); return true; } return false; }
<?php $opt = getopt("c:n:k:"); print_r($opt); if (empty($opt['c']) || empty($opt['n'])) { echo "examples: php client.php -c 100 -n 10000" . PHP_EOL; return; } $clients = $opt['c']; $count = $opt['n']; $size = empty($opt['k']) ? 0 : $opt['k']; require __DIR__ . "/WebSocketClient.php"; $host = '127.0.0.1'; $prot = 9501; $client = new WebSocketClient($host, $prot); $data = $client->connect(); //echo $data; $data = "data"; if (!empty($size)) { $data = str_repeat("A", $size * 1024); } for ($i = 0; $i < $count; $i++) { $client->send("hello swoole, number:" . $i . " data:" . $data); $recvData = ""; //while(1) { $tmp = $client->recv(); if (empty($tmp)) { break; } $recvData .= $tmp; //}
function websocket(Swoole_Benchmark $bc) { static $client = null; static $i; $start = microtime(true); if (empty($client)) { $client = new WebSocketClient($bc->server_config['host'], $bc->server_config['port']); if (!$client->connect()) { echo "connect failed\n"; return false; } $end = microtime(true); $conn_use = $end - $start; $bc->max_conn_time = $conn_use; $i = 0; $start = $end; } /*--------写入Sokcet-------*/ if (!$client->send($bc->send_data)) { echo "send failed\n"; return false; } $end = microtime(true); $write_use = $end - $start; if ($write_use > $bc->max_write_time) { $bc->max_write_time = $write_use; } $start = $end; /*--------读取Sokcet-------*/ $ret = $client->recv(); //var_dump($ret); $i++; if (empty($ret)) { echo $bc->pid, "#{$i}@", " is lost\n"; return false; } $end = microtime(true); $read_use = $end - $start; if ($read_use > $bc->max_read_time) { $bc->max_read_time = $read_use; } return true; }
<?php require __DIR__ . '/WebSocketClient.class.php'; // Connect to the WebSocket server $ws = new WebSocketClient('ws://localhost:1729'); // Send some messages $ws->send('Foo'); $ws->send('Bar'); $ws->send('Baz'); // Close the connection $ws->close(); // Now do the same for SSL $ws = new WebSocketClient('wss://localhost:1730'); $ws->send('Foo'); $ws->send('Bar'); $ws->send('Baz'); $ws->close();
<?php namespace WSSC; require_once './src/ConnectionException.php'; require_once './src/IWscCommons.php'; require_once './src/WscMain.php'; require_once './src/WebSocketClient.php'; $client = new WebSocketClient('ws://localhost:8000/notifications/messanger/vkjsndfvjn23243'); $client->send('{"user_id" : 123}'); echo $client->receive();