workerman+websocket

我的需求是:
某设备通过8093端口向服务器推送事件信息;
服务器通过8093端口接收事件提取有用的信息再通过8090端口向web端推送信息;
web端通过8090端口接受信息帮完成响应的动作;

我遇到的难题:
需要监听8090端口和8093端口,但是这是两个不同的进程,变量数据不共享;
向8090端口推送消息可以主动推送,不需要回调;

解决方案:
Workerman是一款纯PHP开发的开源高性能的PHP socket 服务框架。
http://doc.workerman.net/
用的是workerman的Channel分布式通讯组件解决方案

代码:


use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
require_once __DIR__ . '/Channel/src/Server.php';
require_once __DIR__ . '/Channel/src/Client.php';

// 初始化一个Channel服务端
$channel_server = new Channel\Server('0.0.0.0', 2206);

// websocket服务端
$worker = new Worker('websocket://0.0.0.0:8090');
$worker->count=1;
$worker->name = 'pusher';
$worker->onWorkerStart = function($worker)
{
    // Channel客户端连接到Channel服务端
    Channel\Client::connect('0.0.0.0', 2206);
    // 订阅广播事件
    $event_name = 'sendWeb';
    Channel\Client::on($event_name, function($event_data)use($worker){
        $message = $event_data['content'];
		// echo $message;
		//向订阅了sendWeb事件的客户端推送信息
        foreach($worker->connections as $connection)
        {
            $connection->send(json_encode($message));
        }
    });
};

$worker->onConnect = function($connection)use($worker)
{
    $msg = "workerID:{$worker->id} connectionID:{$connection->id} connected\n";
	echo $msg;
	$info = array("workerID"=>$worker->id,
				  "connectionID"=>$connection->id);
	$connection->send(json_encode($info));
};

//监听来自OM20的事件,并把监听到的数据通过channel服务端推送给订阅了事件的进程
$http_worker = new Worker('tcp://0.0.0.0:8093');
$http_worker->name = 'publisher';
//进程启动时就连上channel服务端
$http_worker->onWorkerStart = function()
{
    Channel\Client::connect('0.0.0.0', 2206);
};
$http_worker->onMessage = function($connection, $data)
{
	$connection->send('ok');
	if(empty($data))
	{
		echo "data is null ";
		return;
	}
	// echo "8093....................................................\n";
	//通过channel服务端推送给订阅了sendWeb事件的进程
	$event_name = 'sendWeb';
	Channel\Client::publish($event_name, array(
	   'content'          => $info
	));
	// echo $data;
};
Worker::runAll();

对代码的理解:
1.要新建一个channel端(2206端口),我的理解是这个channel就像一个中转站,进程间的变量共享问题就是通过这个channel解决的。
2.2206向8090推送事件信息;但是这个推送不是谁都要推送,只会向订阅了客户端推送信息,所以8090要向2206订阅一个事件,我是命名为sendWeb了。
3.从8093收到事件信息就向2206推送;这个推送是向某个事件(sendWeb)进行推送。

前端代码为:

<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <h3>WebSocket协议的客户端程序</h3>
  <button id="btConnect">连接到WS服务器</button>
  <button id="btSendAndReceive">WS服务器发消息并接收消息</button>
  <button id="btClose">断开与WS服务器的连接</button>
  <div id="val"></div>
  <script>
    var wsClient = null; //WS客户端对象
    wsClient = new WebSocket('ws://10.63.15.169:8090');
	
    wsClient.onopen = function(){
		console.log('成功连接服务器')
    }
 
	wsClient.onmessage = function(res){
		let ret = JSON.parse(res.data);
		console.log('data.data为:'+ res.data)
	}
	
	wsClient.onerror = function(){
		console.log('通信发生错误')
	}
	
    btClose.onclick = function(){
      //断开到WS服务器的连接
      wsClient.close();  //向服务器发消息,主动断开连接
      wsClient.onclose = function(){
        //经过客户端和服务器的四次挥手后,二者的连接断开了
        console.log('到服务器的连接已经断开')
      }
    }
  </script>
</body>
</html>

所有代码本人亲测有效

你可能感兴趣的:(socket)