基本环境:
workerman4
gateway-worker3
gatewayclient3
laravel5.8
最近接到新需求,使用workerman接收前端通信数据转发给第三方,这是一个实时转发流程,全程采用ws协议,数据类型二进制的binary message。
新手刚接触这个WK,使用Laravel中的wk例子,基本都是照着例子或者技术先锋们的笔记借鉴,目前前端与wk服务端可实时通信交互。
涉及到外部服务端,想法是:当前端发起ws请求,立马在Events中,在onConnect()中采用AYSN异步类进行ws协议链接第三方,达到一个长链接目的,设置websocketType=BINARY_TYPE_ARRAYBUFFER,但是在这里不清楚如何将这异步send和onMessage转发给对应前端,有些迷茫。
随后 将这半吊子的实例丢进web服务端,只能onconnect,onwensocket 无反应。端口开启2300-2305
代码如下,请多多指正:
class Workerman extends Command
{
//兼容win
protected $signature = 'wk
{action : action}
{--start=all : start}
{--d : daemon mode}';
protected $description = 'Start a Workerman server.';
public function handle()
{
global $argv;
$action = $this->argument('action');
//针对 Windows 一次执行,无法注册多个协议的特殊处理
if ($action === 'single') {
$start = $this->option('start');
if ($start === 'register') {
$this->startRegister();
} elseif ($start === 'gateway') {
$this->startGateWay();
} elseif ($start === 'worker') {
$this->startBusinessWorker();
}
$this->mkdir();
Worker::runAll();
}
}
private function startBusinessWorker()
{
$worker = new BusinessWorker();
$worker->name = 'BusinessWorker';
$worker->count = 1;
$worker->registerAddress = '127.0.0.1:1236';
$worker->eventHandler = \App\Library\Workerman\Events::class; // 可自定义命名
}
rivate function startGateWay()
{
$gateway = new Gateway("websocket://0.0.0.0:8080");
$gateway->name = 'Gateway';
$gateway->count = 1;
$gateway->lanIp = '127.0.0.1'; // 分布式时,填写内网真实IP
$gateway->startPort = 2300;
$gateway->pingInterval = 30; // 心跳时间
$gateway->pingNotResponseLimit = 0; // 1 - 客户端发送心跳; 0 - 服务端发送心跳
$gateway->pingData = '{"type":"ping"}';
$gateway->registerAddress = '127.0.0.1:1236'; // 与business 通信地址,两者一致
$gateway->maxSendBufferSize = 2 * 1024 * 1024;
}
private function startRegister()
{
new Register('text://0.0.0.0:1236'); // 注册监听
}
Events.php
public static $ws_server;
/**
* 客户端连接事件
* @param string $clientId
* @return void
*/
public static function onConnect(string $clientId)
{
echo "Connected\n";
$xfHost = self::getTransfer();
$ws_connection = new AsyncTcpConnection($xfHost);
$ws_connection->WebsocketPingInterval = 30;
$ws_connection->websocketType = Websocket::BINARY_TYPE_BLOB;//BINARY_TYPE_ARRAYBUFFER
$ws_connection->onConnect = function($connection){
echo 'websocket connected';
};
$ws_connection->onWebSocketConnect = function(AsyncTcpConnection $con, $responce){
echo $responce;
// if (empty($con->timer)) {
// //定时发送消息
// $con->timer = Timer::add(0.04, function () use ($con) {
// $con->send();
// });
// }
// $con->send('websocket 连接成功');
};
$ws_connection->onError = function($connection, $code, $msg){
echo "错误:$msg\n";
};
$ws_connection->onClose = function($connection){
echo '链接关闭';
// $connection->reConnect(1);
};
$ws_connection->connect();
self::$ws_server = $ws_connection;
}
/**
* 客户端websocket消息 可以做鉴权业务
* @param string $clientId
* @param string $messageJson
* @return void
*/
public static function onMessage(string $clientId, string $messageJson)
{
$data = json_decode($messageJson, true);
if(!isset($_SESSION['uid'])){
$_SESSION['uid'] = $data['uid'];
}
$filePath = resource_path('image\30s-16k.wav'); // 暂时语音文件读取替代前端通信数据$messageJson
$file = file_get_contents($filePath);
$fdata = substr($file,0, 1280);
self::$ws_server->websocketType = Websocket::BINARY_TYPE_BLOB;
self::$ws_server->send($fdata);// 异步转发 $messageJson
// self::$ws_server->send('{"end":true}');
self::$ws_server->onMessage = function($connection, $data){
echo '远程服务器消息';
echo $data;
$connection->connect();// 这步链接这么写不清楚对不对
//self::sendMessage(200, '{"你好,欢迎到来"}', $data); // 将第三方返回的通信数据转发前端
};
//self::pushFwrite($messageJson); 测试是否内容正常返回
echo '客户端消息:'.$messageJson;
self::log(__FUNCTION__, $clientId, $messageJson);
}
得到的第三方链接started回复,但是之后就是异常问题, 所以不太清楚是代码链接流程有问题还是设置的数据类型有问题。第一次弄那么复杂的技术业务,身边也没有这方面朋友交流,网上帖子大多都是前端与WK通信交互的实例。
以上是本人的不成熟代码,还请各位技术大佬多多指点,非常感谢您的慷慨解囊!!!