swoole 對tcp粘包處理

2021-10-02 01:18:58 字數 2164 閱讀 7852

1,在短時間內資料傳送過快時,會發生粘包現象,比如下面的**,這個現象是雙向的,客戶端,服務端均可能出現此問題

下面只是以客戶端 to 服務端舉例

server.php

<?php 

$host = '0.0.0.0';

//建立server物件,監聽 127.0.0.1:9501埠

$serv = new swoole\server($host, 9501);

//監聽資料接收事件

$serv->on('receive', function ($serv, $fd, $from_id, $data) );

//啟動伺服器

$serv->start();

client.php

<?php 

$client = new swoole_client(swoole_sock_tcp);

//連線到伺服器

if (!$client->connect('127.0.0.1', 9501, 0.5))

//向伺服器傳送資料

for($i=0;$i<3;$i++)

//關閉連線

$client->close();

感覺應該輸出下面這種格式的資料

但其實,會輸出這種

為什麼呢?

2,tcp資料的傳輸,並不是實時的,傳送端和接收端,都有快取機制,因此,出現上面的情況,有兩個原因

1)客戶端,在短時間內快速的傳送了單次小量的資料,在傳送之前被快取了,一次性傳送到了服務端,上面的就是這個原因

2)服務端,沒有及時的拿走資料,導致資料再服務端堆積,粘連

3,swoole有兩種解決方法

1)在服務端新增設定,在客戶端要傳輸的資料末尾新增上 "\r\n"

官方文件:

其原理就是服務端對傳過來的每條資料用分隔符分隔,就像explode()函式

這方法主要有兩個缺點:1,效能非常差;2,如果需要傳輸的資料裡有設定的分隔符,會導致資料被分隔(官方不推薦這個方法)

$serv->set([

'open_eof_split'=> true,

'package_eof' => "\r\n"

]);

2)在客戶端,用pack把資料的長度打包到資料頭,在服務端用unpack解析到資料的長度,再根據長度擷取(推薦)

//客戶端

$data = 'hello';

$len = pack('n',strlen($data));

for($i=0;$i<30;$i++)

//服務端

$length = substr($data,0,4);

$length = unpack('n',$length)[1];

$data_list = str_split($data,$length+4);

foreach($data_list as $data)

3)swoole,對第二種方法,可以直接在服務端設定,就不用像上面的**那樣解析了(客戶端**不能省,還和上面一樣),如果是服務端         傳送給客戶端粘包,那麼就在客戶端設定

文件:

$serv->set([

'open_length_check' => true,

//設定最大資料報尺寸,單位為位元組

'package_max_length' => 1024 * 1024 * 2,

//客戶端的pack函式用的n打包,所以設定n

'package_length_type' => 'n',

//存長度的值從哪開始

'package_length_offset' => 0,

//n 佔4個長度,所以這裡填4

'package_body_offset' => 4,

]);

處理tcp粘包問題

tcp是位元組流,無邊界,udp是訊息,是有邊界的。就是udp返回的就是乙個訊息。所以tcp會產生粘包問題。如何解決粘包問題,所以我們要在應用層維護訊息與訊息的邊界。比如說定長包,包尾加 r n ftp 包頭加包體長度,更複雜的應用層協議。readn接受確切資料的讀操作 cli include in...

swoole使用tcp的時候粘包問題

文章參考位址使用自定義協議粘包 如何解決swoole中使用tcp的粘包問題 兩種方式 第一種通過在swoole server的set中設定分隔符 1 在你的client端,呼叫send時加 name xiaomi client send name.php eol 2 在server端 server ...

TCP粘包的拆包處理

因為tcp是流式處理的,所以包沒有邊界,必須設計乙個包頭,裡面表示包的長度 一般用位元組表示 根據這個來逐個拆包。如果對於傳送 接收頻率不高的話,一般也就不做拆包處理了,因為不大可能有粘包現象。以下是粘包和拆包的分析 用qt的tcpsocket讀出的資料來拆 1 m imp m thread boo...