




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第詳解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.總結6.擴展知識6.1字節(jié)序
1.數(shù)據(jù)發(fā)送過程
首先由客戶端將數(shù)據(jù)發(fā)往緩沖區(qū)(服務端并不是直接收到的),對于客戶端來說,這次的數(shù)據(jù)即是發(fā)送成功了,對于服務端是否真正的收到他是不知道的,然后再由服務端從緩沖區(qū)中讀取數(shù)據(jù)。圖解:
2.什么是數(shù)據(jù)邊界
因為TCP是流式傳輸,對于服務端來說并不知道此時在緩沖區(qū)內的數(shù)據(jù)是一次請求還是兩次請求的,所以在服務端接收數(shù)據(jù)時需要根據(jù)指定字符或約定長度來對數(shù)據(jù)進行分包,這個分包的標志即是數(shù)據(jù)邊界。否則可能會出現(xiàn)一次讀取兩條或多條數(shù)據(jù),造成讀取、解析數(shù)據(jù)出錯。
2.1代碼演示
可以用代碼實現(xiàn)一下,假設客戶端死循環(huán)往緩沖區(qū)不停輸入“1”,即相當于每次的報文內容都是1,那么在服務端讀取時收到的數(shù)據(jù)就是隨機長度的。
客戶端代碼:
$client=newSwoole\Client(SWOOLE_SOCK_TCP);
if($client-connect('',9501,-1)){
while(true){
$client-send(1);
$client-close();
服務端代碼:
$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){
});
運行結果
可以看到運行結果,服務端獲取到的數(shù)據(jù)完全是隨機的,有長有短,那么接下來我們說下如何解決這個問題。
3.EOF解決方案
第一種解決方案類似于我們http請求頭的分隔符,在每次發(fā)送的數(shù)據(jù)包結尾處使用\r\n(可以配置)來結尾,當服務端從緩沖區(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)結尾是\r\n時,才會投遞給worker進程,也就是我們的onReceive回調,否則會一直拼接數(shù)據(jù)包,直到超出緩沖區(qū)或者超時才終止。但此方法有一個問題是可能會一次性收到多個數(shù)據(jù)包,因為他是從數(shù)據(jù)包的結尾處來進行檢查的,在數(shù)據(jù)內容中存在\r\n時程序并不會發(fā)現(xiàn),需要我們自己在應用代碼中再次使用\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();
服務端代碼
$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();
運行結果
3.2open_eof_split
配置方式:
$server-set([
'open_eof_split'=true,
'package_eof'="\r\n"
]);
這種配置方式,服務端會對客戶端發(fā)來的數(shù)據(jù)逐個字符進行檢查,遇到\r\n就發(fā)送給worker進程,可以有效實現(xiàn)分包,但缺點是性能比較差。
運行結果:可以看到每次接收到一個HelloWorld(代碼我就不貼了,只把服務端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ù)處理僅進行指針偏移,性能非常高,推薦使用。
可見官方是推薦使用這種方式的,就是配置比其他方案要復雜一些,首先貼一下配置:
$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設置為N
'package_body_offset'=16,
//設置最大數(shù)據(jù)包尺寸,單位為字節(jié)
'package_max_length'=81920
]);
下面是一個數(shù)據(jù)包結構例子,可以很好的體現(xiàn)了字段含義。
以上通信協(xié)議的設計中,包頭長度為4個整型,16字節(jié),length長度值在第3個整型處。因此package_length_offset設置為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)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 暴雷和解協(xié)議書
- 道路維護勞務合同協(xié)議
- 車輛單方贈予合同協(xié)議
- 高級審計師考試成功分享試題及答案
- 油價承壓協(xié)議書
- 清收委托協(xié)議書
- 迅鐳激光技術協(xié)議合同書
- 道閘欄桿采購協(xié)議合同
- 還房協(xié)議和購房合同
- 歌廳入伙協(xié)議書
- 矯形鞋墊產(chǎn)品技術要求標準2024年版
- 2024年江西省南昌市中考生物·地理合卷試卷真題(含答案逐題解析)
- Photoshop平面設計與制作智慧樹知到期末考試答案章節(jié)答案2024年黑龍江農業(yè)工程職業(yè)學院(松北校區(qū))
- DL∕T 796-2012 風力發(fā)電場安全規(guī)程
- 急診科骨髓腔穿刺及輸液技術
- 《視覺傳達設計》題集
- 法律人生智慧樹知到期末考試答案章節(jié)答案2024年中國石油大學(華東)
- JGJ120-2012 建筑基坑支護技術規(guī)程
- 企業(yè)員工保密協(xié)議書范本
- 美國文學概論智慧樹知到期末考試答案章節(jié)答案2024年吉林師范大學
- 2024年福建省三明市中考數(shù)學二檢試卷(含解析)
評論
0/150
提交評論