swoole json不完整怎么辦

swoole json不完整怎么辦

swoole json不完整怎么辦?

swoole客戶端與服務端收發數據完整性問題解決

一、下面這個實例,啟動swoole服務后,監聽9501端口,接收從客戶端發來的數據,原樣返回。

class?Server { ????private?$serv; ????public?function?__construct()?{ ????????$this->serv?=?new?swoole_server("127.0.0.1",?9501); ????????$this->serv->set(array( ????????????'worker_num'?????=>?4,???//一般設置為服務器CPU數的1-4倍 ????????????'daemonize'??????=>?1,??//以守護進程執行 ????????????'max_request'?????=>?2000, ????????????'dispatch_mode'????=>?2,//進程數據包分配模式?1平均分配,2按FD取摸固定分配,3搶占式分配 ????????????'task_worker_num'???=>?8,??//task進程的數量 ????????????"task_ipc_mode?"???=>?3?,??//使用消息隊列通信,并設置為爭搶模式 ????????????"log_file"??????=>?"./log/taskqueueu.log"?,//日志 ????????)); ????????$this->serv->on('Receive',?array($this,'onReceive'));//接收到數據時回調此函數 ????????$this->serv->start(); ????} ????public?function?onReceive(swoole_server?$serv,?$fd,?$from_id,?$data?)?{ ????????????????$serv->send($fd,?$data); ????????????????????????usleep(500);?//不加延時的話,經常兩條數據被合并成一條返回了。 ????????????????????????$serv->close($fd); ????}??? ????public?function?onClose(swoole_server?$serv,?$fd)?{ ????????????????$serv->send($fd,?'CLOSED'); ????}??? }

直接new Server啟動服務端。

二、啟動swoole客戶端,向服務端發數據,并接收返回。

$client?=?new?swoole_client(SWOOLE_SOCK_TCP); if?(!$client->connect('127.0.0.1',?9501,?-1)) { ????exit("connect?failed.?Error:?{$client->errCode}n"); } $data=[ ????????'type'=>1,? ????????'data'=>array( ????????????????'PlatformCode'=>'...........很長的數據.', ????????????) ???]; $sender=$client->send(json_encode($data)."rnrn"); while($result?=?$client->recv()){ ????if($result=='CLOSED'){ ????????????echo?"任務結束。byebye~rn"; ????????????break; ????}else{ ??????echo?$result; ??} } $client->close();

當發送比較大的數據包時,會發現接收到的json包是不完整的,可以使用EOF協議處理的方式來解決,比如在服務端設置:

????$serv->set( ????????array('open_eof_split'?=>?TRUE,?'package_eof'?=>?"rnrn") ????);

這樣,’rnrn’就成為EOF協議結束符。

發送數據包時,在包結尾添加上’rnrn’,接口數據時遇到這個字符就認為數據接收完畢,如此就保證的數據的完整性。

注:數據包中不能出現’rnrn’字符,否則會出現分包錯誤。

Swoole的Server和異步Client都是在onReceive回調函數中處理數據包,當設置了協議處理后,只有收到一個完整數據包時才會觸發onReceive事件

另外一種方式,也可以預先設定好要發送的包的長度,如:

$server->set(array( ????????'open_length_check'?=>?true, ????????'package_max_length'?=>?81920, ????????'package_length_type'?=>?'n',?//see?php?pack() ????????'package_length_offset'?=>?0, ????????'package_body_offset'?=>?2, ));

可以固定包的長度來確保數據的完整性,官方注釋如下:

固定包頭的協議非常通用,在BAT的服務器程序中經常能看到。這種協議的特點是一個數據包總是由包頭+包體2部分組成。包頭由一個字段指定了包體或整個包的長度,長度一般是使用2字節/4字節整數來表示。服務器收到包頭后,可以根據長度值來精確控制需要再接收多少數據就時完整的數據包。Swoole的配置可以很好的支持這種協議,可以靈活地設置4項參數應對所有情況。

Swoole的Server和異步Client都是在onReceive回調函數中處理數據包,當設置了協議處理后,只有收到一個完整數據包時才會觸發onReceive事件。同步客戶端在設置了協議處理后,調用 $client->recv() 不再需要傳入長度,recv函數在收到完整數據包或發生錯誤后返回。

以上就是

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享