**需求**:用戶發表了某篇文章,其他人閱讀后發表評論,評論經過后臺審核,審核后通知作者。
### **方案一:**
審核操作改為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標記