**需求**:用户发表了某篇文章,其他人阅读后发表评论,评论经过后台审核,审核后通知作者。
### **方案一:**
审核操作改为ajax操作,success回调内再new一个websocket客户端,然后send?可以,但是这显然不是一个很好的操作。
要想与websocket server通信,客户端只能是websocket客户端!既然我们刚刚否决了new一个websocket客户端,那是要怎么做呢?
### **方案二:**
首先我们要想让web应用同server进行“互撩”,swoole\_client少不了,既然有swoole\_client,swoole\_server肯定也少不了。但是目前server正在跑websocket,难不成我们在单独跑一个tcp server?对,我们就是要在websocket server的基础之上,想办法再跑一个tcp server。
为了使用多端口复合协议,swoole为server提供了listen方法,可以让当前server监听新的端口。
比如我们可以让刚刚创建的websocket server额外监听9502端口,这个端口主要负责tcp的工作。
$this->tcp = $this->server->listen('127.0.0.1', 9502, SWOOLE_SOCK_TCP);
//关闭websocket模式
$this->server->set([
'open_websocket_protocol' => false,
]);
$this->tcp->set([
'open_eof_check' => true, //打开EOF检测
'package_eof' => "\r\n", //设置EOF
'open_eof_split' => true, // 自动分包
]);
$this->_tcp->on('Receive', [$this, 'onReceive']);
listen函数返回的是swoole\_server\_port对象,需要注意的是swoole\_server\_port的set函数只能设置一些特定的参数,比如socket参数、协议相关等,像worker\_num、log\_file、max\_request等等这些都是不支持的。就tcp服务器而言,swoole\_server\_port对象也仅仅对onConnect\\onReceive\\onClose这三个回调支持,其他的一律不可用,详细可翻阅swoole手册查看。
**再来看下我们现在的流程**
1、用户发表评论 => 评论进入审核状态 ;很明显这个过程我们不需要做什么
2、管理员审核该评论 => 通知文章作者;
server端除了刚刚设置的$this->tcp一段代码之外,我们单独绑定了onReceive回调,下面看onReceive回调的实现
public function onReceive($serv, $fd, $fromId, $data) {
try {
$data = json_decode($data, true);
if (!isset($data['event'])) {
throw new \Exception("params error, needs event param.", 1);
}
$method = $data['event']; // 调起对应的方法
if(!method_exists($this, $method)) {
throw new \Exception("params error, not support method.", 1);
}
$this->$method($fd, $data);
return true;
} catch (\Exception $e) {
$msg = $e->getMessage();
throw new \Exception("{$msg}", 1);
}
}
我们再来看websocket客户端的代码,改代码是管理员审核之后调用。
class Client {
private $client;
public function __construct () {
$this->client = new Swoole\\Client(SWOOLE_SOCK_TCP);
if (!$this->client->connect('127.0.0.1', 9502)) {
$msg = 'swoole client connect failed.';
throw new \Exception("Error: {$msg}.");
}
}
public function sendData ($data) {
$data = $this->togetherDataByEof($data);
$this->client->send($data);
}
public function togetherDataByEof($data) {
if (!is_array($data)) {
return false;
}
return json_encode($data) . "\r\n";
}
}
$client = new Client;
$client->sendData([
'event' => 'alertTip',
'toUid' => 100,
]);
注意:发送数据的末尾需要拼接EOF标记