websocket协议RFC文档地址:https://tools.ietf.org/html/rfc6455,以下是用纯PHP实现的一个轻量的websocket客户端,可以用来与websocket服务器进行通信。
<?php
namespace library\util;
use Exception;
class BadUriException extends Exception{}
class ServerConnectException extends Exception{}
class HandshakeException extends Exception{}
class BadFrameException extends Exception{}
class SocketRWException extends Exception{}
class WebSocketClient
{
const PROTOCOL_WS = 'ws';
const PROTOCOL_WSS = 'wss';
const HTTP_HEADER_SEPARATION_MARK = "\r\n";
const HTTP_HEADER_END_MARK = "\r\n\r\n";
const UUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
const PACKET_SIZE = (1 << 15);
// 还有后续帧
const OPCODE_CONTINUATION_FRAME = 0;
// 文本帧
const OPCODE_TEXT_FRAME = 1;
// 二进制帧
const OPCODE_BINARY_FRAME = 2;
// 关闭连接
const OPCODE_CLOSE = 8;
// ping
const OPCODE_PING = 9;
// pong
const OPCODE_PONG = 10;
const FRAME_LENGTH_LEVEL_1_MAX = 125;
const FRAME_LENGTH_LEVEL_2_MAX = 65535;
private $protocol;
private $host;
private $port;
private $path;
private $sock;
private $secWebSocketKey;
private $handshakePass = false;
private $readBuf;
private $currentReadBufLen;
private $readBufPos;
private $closed = false;
/**
* WebSocketClient constructor.
* @param string $wsUri
* @param float $connectTimeout 设置连接服务器的超时时间
* @param float $rwTimeout 设置读写数据的超时时间
* @throws Exception
*/
public function __construct($wsUri, $connectTimeout = 1.0, $rwTimeout = 5.0)
{
$this->parseUri($wsUri);
$this->connect($connectTimeout, $rwTimeout);
$this->handshake();
$this->initReadBuf();
}
/**
* 解析websocket连接地址
* @param $wsUri
* @throws BadUriException
*/
protected function parseUri($wsUri)
{
$uriData = parse_url($wsUri);
if (!$uriData) {
throw new BadUriException('不正确的ws uri格式', __LINE__);
}
if ($uriData['scheme'] != self::PROTOCOL_WS && $uriData['scheme'] != self::PROTOCOL_WSS) {
throw new BadUriException('ws的uri必须是以ws://或wss://开头', __LINE__);
}
$this->protocol = $uriData['scheme'];
$this->host = $uriData['host'];
if ($uriData['port']) {
$this->port = (int)$uriData['port'];
} else {
if ($this->protocol == self::PROTOCOL_WSS) {
$this->port = 443;
} else {
$this->port = 80;
}
}
$this->path = $uriData['path'] ?: '/';
if ($uriData['query']) {
$this->path .= '?' . $uriData['query'];
}
if ($uriData['fragment']) {
$this->path .= '#' . $uriData['fragment'];
}
}
/**
* 连接websocket服务器
* @param float $timeout 连接服务器的超时时间
* @param float $rwTimeout 设置读写数据的超时时间
* @throws ServerConnectException
*/
protected function connect($timeout, $rwTimeout)
{
$this->sock = stream_socket_client(
($this->protocol == self::PROTOCOL_WSS ? 'ssl://' : 'tcp://') . $this->host . ':' . $this->port,
$errno,
$errstr,
$timeout
);
if (!$this->sock) {
if ($errstr) {
throw new ServerConnectException('连接ws服务器失败:' . $errstr, $errno);
}
throw new ServerConnectException('连接ws服务器失败: 未知错误', __LINE__);

本文介绍了一个使用纯PHP编写的轻量级WebSocket客户端,详细展示了如何解析WebSocket连接地址、建立连接、握手、发送和接收数据的过程。客户端支持文本帧、二进制帧、关闭连接、ping和pong操作。
最低0.47元/天 解锁文章
1391





