开源 企业版 高校版 私有云 模力方舟 AI 队友
代码拉取完成,页面将自动刷新
加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
已有帐号? 立即登录
文件
master
分支 (2)
master
1.0.0
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
项目仓库所选许可证以仓库主分支所使用许可证为准
master
分支 (2)
master
1.0.0
克隆/下载
克隆/下载
提示
下载代码请复制以下命令到终端执行
为确保你提交的代码身份被 Gitee 正确识别,请执行以下命令完成配置
初次使用 SSH 协议进行代码克隆、推送等操作时,需按下述提示完成 SSH 配置
1 生成 RSA 密钥
2 获取 RSA 公钥内容,并配置到 SSH公钥
在 Gitee 上使用 SVN,请访问 使用指南
使用 HTTPS 协议时,命令行会出现如下账号密码验证步骤。基于安全考虑,Gitee 建议 配置并使用私人令牌 替代登录密码进行克隆、推送等操作
Username for 'https://gitee.com': userName
Password for 'https://userName@gitee.com': # 私人令牌
master
分支 (2)
master
1.0.0
bridge
/
src
/
WebSocket
/
WsBridge.php
bridge
/
src
/
WebSocket
/
WsBridge.php
WsBridge.php 6.70 KB
一键复制 编辑 原始数据 按行查看 历史
wpjscc 提交于 2024年08月10日 09:28 +08:00 . modify namespace
<?php
namespace ReactphpX\Bridge\WebSocket;
use ReactphpX\Bridge\Http\HttpBridgeInterface;
use ReactphpX\Bridge\Interface\MessageComponentInterface;
use ReactphpX\Bridge\Info;
use React\Stream\DuplexStreamInterface;
use Ratchet\RFC6455\Messaging\MessageInterface;
use Ratchet\RFC6455\Messaging\FrameInterface;
use Ratchet\RFC6455\Messaging\Frame;
use Ratchet\RFC6455\Messaging\MessageBuffer;
use Ratchet\RFC6455\Messaging\CloseFrameChecker;
use Ratchet\RFC6455\Handshake\ServerNegotiator;
use Ratchet\RFC6455\Handshake\RequestVerifier;
use GuzzleHttp\Psr7\Message;
use React\Stream\CompositeStream;
use React\Stream\ThroughStream;
use React\EventLoop\LoopInterface;
class WsBridge implements HttpBridgeInterface
{
protected $component;
protected $streams;
/**
* @var \Ratchet\RFC6455\Messaging\CloseFrameChecker
*/
private $closeFrameChecker;
/**
* @var \Ratchet\RFC6455\Handshake\ServerNegotiator
*/
private $handshakeNegotiator;
/**
* @var \Closure
*/
private $ueFlowFactory;
/**
* @var \Closure
*/
private $pongReceiver;
/**
* @var \Closure
*/
private $msgCb;
public function __construct(MessageComponentInterface $component)
{
if (bin2hex('✓') !== 'e29c93') {
throw new \DomainException('Bad encoding, unicode character ✓ did not match expected value. Ensure charset UTF-8 and check ini val mbstring.func_autoload');
}
$this->component = $component;
$this->streams = new \SplObjectStorage();
$this->msgCb = function (DuplexStreamInterface $stream, MessageInterface $msg) {
$this->component->onMessage($stream, $msg);
};
$this->closeFrameChecker = new CloseFrameChecker;
$this->handshakeNegotiator = new ServerNegotiator(new RequestVerifier);
$this->handshakeNegotiator->setStrictSubProtocolCheck(true);
if ($component instanceof WsServerInterface) {
$this->handshakeNegotiator->setSupportedSubProtocols($component->getSubProtocols());
}
$this->pongReceiver = function () {
};
$reusableUnderflowException = new \UnderflowException;
$this->ueFlowFactory = function () use ($reusableUnderflowException) {
return $reusableUnderflowException;
};
}
public function onOpen(DuplexStreamInterface $stream, $info = null)
{
$request = $info['request'] ?? null;
if (null === $request) {
throw new \UnexpectedValueException('$request can not be null');
}
$response = $this->handshakeNegotiator->handshake($request)->withHeader('X-Powered-By', 'reactphp-x/Bridge/alpha');
$stream->write(Message::toString($response));
if (101 !== $response->getStatusCode()) {
return $stream->close();
}
$middleInStream = new ThroughStream();
$middleOutStream = new ThroughStream(function ($data) use (&$streamer) {
if ($data instanceof Frame) {
$streamer->sendFrame($data);
} else if ($data instanceof MessageInterface) {
$streamer->sendMessage($data->getPayload(), true, $data->isBinary());
} else {
$streamer->sendMessage($data);
}
});
$middleStream = new CompositeStream($middleInStream, $middleOutStream);
$middleStream->on('close', function () use ($stream) {
if ($stream) {
$stream->end(new Frame(pack('n', 1000), true, Frame::OP_CLOSE));
}
});
$streamer = new MessageBuffer(
$this->closeFrameChecker,
function (MessageInterface $msg) use ($middleStream) {
$cb = $this->msgCb;
$middleStream->emit('data', [$msg->getPayload()]);
$cb($middleStream, $msg);
},
function (FrameInterface $frame) use ($middleStream) {
$this->onControlFrame($frame, $middleStream);
},
true,
$this->ueFlowFactory,
null,
null,
[$stream, 'write']
);
$info['streamer'] = $streamer;
$info['middle_stream'] = $middleStream;
$this->streams->attach($stream, $info);
$this->component->onOpen($middleStream, $info);
}
public function onClose(DuplexStreamInterface $stream, $reason = null)
{
if ($this->streams->contains($stream)) {
$middleStream = $this->streams[$stream]['middle_stream'];
$middleStream->close();
$this->streams->detach($stream);
$this->component->onClose($middleStream, $reason);
}
}
public function onError(DuplexStreamInterface $stream, \Exception $e)
{
if ($this->streams->contains($stream)) {
$this->streams[$stream]['middle_stream']->emit('error', [$e]);
$this->component->onError($this->streams[$stream]['middle_stream'], $e);
} else {
$stream->end(new Frame(pack('n', 1000), true, Frame::OP_CLOSE));
}
}
public function onMessage(DuplexStreamInterface $stream, $msg)
{
$this->streams[$stream]['streamer']->onData($msg);
}
public function enableKeepAlive(LoopInterface $loop, $interval = 30)
{
$lastPing = new Frame(uniqid(), true, Frame::OP_PING);
$pingedConnections = new \SplObjectStorage;
$splClearer = new \SplObjectStorage;
$this->pongReceiver = function (FrameInterface $frame, $wsConn) use ($pingedConnections, &$lastPing) {
if ($frame->getPayload() === $lastPing->getPayload()) {
$pingedConnections->detach($wsConn);
}
};
$loop->addPeriodicTimer((int)$interval, function () use ($pingedConnections, &$lastPing, $splClearer) {
foreach ($pingedConnections as $wsConn) {
$wsConn->close();
}
$pingedConnections->removeAllExcept($splClearer);
$lastPing = new Frame(uniqid(), true, Frame::OP_PING);
foreach ($this->streams as $stream) {
$stream->write($lastPing);
$pingedConnections->attach($wsConn);
}
});
}
private function onControlFrame(FrameInterface $frame, DuplexStreamInterface $stream)
{
switch ($frame->getOpCode()) {
case Frame::OP_CLOSE:
$stream->end($frame);
break;
case Frame::OP_PING:
$stream->write(new Frame($frame->getPayload(), true, Frame::OP_PONG));
break;
case Frame::OP_PONG:
$pongReceiver = $this->pongReceiver;
$pongReceiver($frame, $stream);
break;
}
}
}
Loading...
举报
举报成功
我们将于2个工作日内通过站内信反馈结果给你!
请认真填写举报原因,尽可能描述详细。
请选择举报类型
取消
发送
误判申诉

此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。

如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。

取消
提交

发行版

暂无发行版

贡献者

全部

语言

近期动态

不能加载更多了
编辑仓库简介
简介内容
主页
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/reactphp-framework/bridge.git
git@gitee.com:reactphp-framework/bridge.git
reactphp-framework
bridge
bridge
master
点此查找更多帮助

搜索帮助

评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册

AltStyle によって変換されたページ (->オリジナル) /