溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

swoole json不完整的解決方法

發(fā)布時(shí)間:2021-01-19 09:38:26 來源:億速云 閱讀:369 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關(guān)swoole json不完整的解決方法的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

swoole json不完整怎么辦?

swoole客戶端與服務(wù)端收發(fā)數(shù)據(jù)完整性問題解決

一、下面這個(gè)實(shí)例,啟動(dòng)swoole服務(wù)后,監(jiān)聽9501端口,接收從客戶端發(fā)來的數(shù)據(jù),原樣返回。

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

直接new Server啟動(dòng)服務(wù)端。

二、啟動(dòng)swoole客戶端,向服務(wù)端發(fā)數(shù)據(jù),并接收返回。

$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'=>'...........很長(zhǎng)的數(shù)據(jù).',
            )
   ];
$sender=$client->send(json_encode($data)."\r\n\r\n");
while($result = $client->recv()){
    if($result=='CLOSED'){
            echo "任務(wù)結(jié)束。byebye~\r\n";
            break;
    }else{
      echo $result;
  }
}
$client->close();

當(dāng)發(fā)送比較大的數(shù)據(jù)包時(shí),會(huì)發(fā)現(xiàn)接收到的json包是不完整的,可以使用EOF協(xié)議處理的方式來解決,比如在服務(wù)端設(shè)置:

    $serv->set(
        array('open_eof_split' => TRUE, 'package_eof' => "\r\n\r\n")
    );

這樣,'\r\n\r\n'就成為EOF協(xié)議結(jié)束符。

發(fā)送數(shù)據(jù)包時(shí),在包結(jié)尾添加上'\r\n\r\n',接口數(shù)據(jù)時(shí)遇到這個(gè)字符就認(rèn)為數(shù)據(jù)接收完畢,如此就保證的數(shù)據(jù)的完整性。

注:數(shù)據(jù)包中不能出現(xiàn)'\r\n\r\n'字符,否則會(huì)出現(xiàn)分包錯(cuò)誤。

Swoole的Server和異步Client都是在onReceive回調(diào)函數(shù)中處理數(shù)據(jù)包,當(dāng)設(shè)置了協(xié)議處理后,只有收到一個(gè)完整數(shù)據(jù)包時(shí)才會(huì)觸發(fā)onReceive事件。

另外一種方式,也可以預(yù)先設(shè)定好要發(fā)送的包的長(zhǎng)度,如:

$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,
));

可以固定包的長(zhǎng)度來確保數(shù)據(jù)的完整性,官方注釋如下:

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

Swoole的Server和異步Client都是在onReceive回調(diào)函數(shù)中處理數(shù)據(jù)包,當(dāng)設(shè)置了協(xié)議處理后,只有收到一個(gè)完整數(shù)據(jù)包時(shí)才會(huì)觸發(fā)onReceive事件。同步客戶端在設(shè)置了協(xié)議處理后,調(diào)用 $client->recv() 不再需要傳入長(zhǎng)度,recv函數(shù)在收到完整數(shù)據(jù)包或發(fā)生錯(cuò)誤后返回。

感謝各位的閱讀!關(guān)于“swoole json不完整的解決方法”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI