詳解Swoole TCP流數(shù)據(jù)邊界問題解決方案_第1頁
詳解Swoole TCP流數(shù)據(jù)邊界問題解決方案_第2頁
詳解Swoole TCP流數(shù)據(jù)邊界問題解決方案_第3頁
詳解Swoole TCP流數(shù)據(jù)邊界問題解決方案_第4頁
詳解Swoole TCP流數(shù)據(jù)邊界問題解決方案_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第詳解SwooleTCP流數(shù)據(jù)邊界問題解決方案目錄1.數(shù)據(jù)發(fā)送過程2.什么是數(shù)據(jù)邊界2.1代碼演示3.EOF解決方案3.1open_eof_check3.2open_eof_split3.3open_eof_check和open_eof_split差異4.固定包頭+包體解決方案5.總結(jié)6.擴展知識6.1字節(jié)序

1.數(shù)據(jù)發(fā)送過程

首先由客戶端將數(shù)據(jù)發(fā)往緩沖區(qū)(服務(wù)端并不是直接收到的),對于客戶端來說,這次的數(shù)據(jù)即是發(fā)送成功了,對于服務(wù)端是否真正的收到他是不知道的,然后再由服務(wù)端從緩沖區(qū)中讀取數(shù)據(jù)。圖解:

2.什么是數(shù)據(jù)邊界

因為TCP是流式傳輸,對于服務(wù)端來說并不知道此時在緩沖區(qū)內(nèi)的數(shù)據(jù)是一次請求還是兩次請求的,所以在服務(wù)端接收數(shù)據(jù)時需要根據(jù)指定字符或約定長度來對數(shù)據(jù)進行分包,這個分包的標志即是數(shù)據(jù)邊界。否則可能會出現(xiàn)一次讀取兩條或多條數(shù)據(jù),造成讀取、解析數(shù)據(jù)出錯。

2.1代碼演示

可以用代碼實現(xiàn)一下,假設(shè)客戶端死循環(huán)往緩沖區(qū)不停輸入“1”,即相當于每次的報文內(nèi)容都是1,那么在服務(wù)端讀取時收到的數(shù)據(jù)就是隨機長度的。

客戶端代碼:

$client=newSwoole\Client(SWOOLE_SOCK_TCP);

if($client-connect('',9501,-1)){

while(true){

$client-send(1);

$client-close();

服務(wù)端代碼:

$server=newSwoole\Server('',9501);

$server-on('connect',function($server,$fd){

echo"client:".$fd."connect";

$server-on('receive',function($server,$fd,$from_id,$data){

echo"receive:".$data.PHP_EOL;

$server-on('close',function($server){

});

運行結(jié)果

可以看到運行結(jié)果,服務(wù)端獲取到的數(shù)據(jù)完全是隨機的,有長有短,那么接下來我們說下如何解決這個問題。

3.EOF解決方案

第一種解決方案類似于我們http請求頭的分隔符,在每次發(fā)送的數(shù)據(jù)包結(jié)尾處使用\r\n(可以配置)來結(jié)尾,當服務(wù)端從緩沖區(qū)中讀取數(shù)據(jù),根據(jù)指定字符來分割數(shù)據(jù)包,EOF有兩種配置方案:

3.1open_eof_check

首先放出配置方式:

$server-set([

'open_eof_check'=true,

'package_eof'="\r\n"

]);

這種配置方式會對客戶端發(fā)來的數(shù)據(jù)包進行檢測,當發(fā)現(xiàn)結(jié)尾是\r\n時,才會投遞給worker進程,也就是我們的onReceive回調(diào),否則會一直拼接數(shù)據(jù)包,直到超出緩沖區(qū)或者超時才終止。但此方法有一個問題是可能會一次性收到多個數(shù)據(jù)包,因為他是從數(shù)據(jù)包的結(jié)尾處來進行檢查的,在數(shù)據(jù)內(nèi)容中存在\r\n時程序并不會發(fā)現(xiàn),需要我們自己在應(yīng)用代碼中再次使用\r\n來拆分數(shù)據(jù)包。

客戶端運行代碼

$client=newSwoole\Client(SWOOLE_SOCK_TCP);

if($client-connect('',9501,-1)){

while(true){

$send2="HelloWorld\r\n";

$client-send($send2);

$client-close();

服務(wù)端代碼

$server=newSwoole\Server('',9501);

$server-set([

'open_eof_check'=true,

'package_eof'="\r\n"

$server-on('connect',function($server,$fd){

echo"client:".$fd."connect";

$server-on('receive',function($server,$fd,$from_id,$data){

echo"receive:".$data;

$server-on('close',function($server){

$server-start();

運行結(jié)果

3.2open_eof_split

配置方式:

$server-set([

'open_eof_split'=true,

'package_eof'="\r\n"

]);

這種配置方式,服務(wù)端會對客戶端發(fā)來的數(shù)據(jù)逐個字符進行檢查,遇到\r\n就發(fā)送給worker進程,可以有效實現(xiàn)分包,但缺點是性能比較差。

運行結(jié)果:可以看到每次接收到一個HelloWorld(代碼我就不貼了,只把服務(wù)端set配置改一下,其他都一樣)

3.3open_eof_check和open_eof_split差異

open_eof_check只檢查接收數(shù)據(jù)的末尾是否為EOF,因此它的性能最好,幾乎沒有消耗

open_eof_check無法解決多個數(shù)據(jù)包合并的問題,比如同時發(fā)送兩條帶有EOF的數(shù)據(jù),底層可能會一次全部返回

open_eof_split會從左到右對數(shù)據(jù)進行逐字節(jié)對比,查找數(shù)據(jù)中的EOF進行分包,性能較差。但是每次只會返回一個數(shù)據(jù)包

4.固定包頭+包體解決方案

引用一段官方文檔的描述:

包長檢測提供了固定包頭+包體這種格式協(xié)議的解析。啟用后,可以保證Worker進程onReceive每次都會收到一個完整的數(shù)據(jù)包。

長度檢測協(xié)議,只需要計算一次長度,數(shù)據(jù)處理僅進行指針偏移,性能非常高,推薦使用。

可見官方是推薦使用這種方式的,就是配置比其他方案要復(fù)雜一些,首先貼一下配置:

$server-set([

//打開包長檢測特性

'package_length_check'=true,

//包頭中某個字段作為包長度的值,底層支持了10種長度類型??蓞⒖紁ack()方法

'package_length_type'='N',

//length長度值在包頭的第幾個字節(jié)。

'package_length_offset'=8,

//從第幾個字節(jié)開始計算長度,一般有2種情況:

//length的值包含了整個包(包頭+包體),package_body_offset為0

//包頭長度為N字節(jié),length的值不包含包頭,僅包含包體,package_body_offset設(shè)置為N

'package_body_offset'=16,

//設(shè)置最大數(shù)據(jù)包尺寸,單位為字節(jié)

'package_max_length'=81920

]);

下面是一個數(shù)據(jù)包結(jié)構(gòu)例子,可以很好的體現(xiàn)了字段含義。

以上通信協(xié)議的設(shè)計中,包頭長度為4個整型,16字節(jié),length長度值在第3個整型處。因此package_length_offset設(shè)置為8,0-3字節(jié)為type,4-7字節(jié)為uid,8-11字節(jié)為length,12-15字節(jié)為serid。

下面來說一下代碼實現(xiàn):

客戶端代碼:

$client=newSwoole\Client(SWOOLE_SOCK_TCP);

$data="123456789012345678901234567890"

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論