前面的工作都準(zhǔn)備好后,就可以開始入手swoole了硫惕。
現(xiàn)在就簡單的對以下幾個模塊進行簡單的上手入門茧痕,當(dāng)然官方文檔也有對應(yīng)的使用方法,這里也只是簡單的介紹上手疲憋。
HTML5的websocket文檔:https://www.runoob.com/html/html5-websocket.html
目錄:
Swoole的快速起步
? ? 1凿渊、tcp服務(wù)的學(xué)習(xí)和使用
? ? 2、udp服務(wù)的學(xué)習(xí)和使用
? ? 3、tcp埃脏、udp的介紹和它們的區(qū)別對比
? ? 4搪锣、tcp和udp客戶端的使用
? ? 5、Http服務(wù)的學(xué)習(xí)和使用
? ? 6彩掐、websocket服務(wù)的使用
正文:?tcp服務(wù)和udp服務(wù)的學(xué)習(xí)和使用
一构舟、swoole支持的服務(wù)
swoole創(chuàng)建一個異步服務(wù)器程序,可以支持TCP堵幽、UDP狗超、UnixSocket?3種協(xié)議,支持IPv4和IPv6朴下,支持SSL/TLS單向雙向證書的隧道加密努咐。使用者無需關(guān)注底層實現(xiàn)細(xì)節(jié),僅需要設(shè)置網(wǎng)絡(luò)事件的回調(diào)函數(shù)即可殴胧。
二渗稍、swoole運行的流程圖(來自官方文檔)
三、進程/線程結(jié)構(gòu)圖(來自官方文檔)
四团滥、通過第二點的swoole流程圖竿屹,實現(xiàn)一個簡單tcp服務(wù)的過程為:
(1)創(chuàng)建一個異步Server對象,具體可以參考server的函數(shù)文檔(server的相關(guān)函數(shù))
$serv = new Server(string $host, int $port = 0, int $mode = SWOOLE_PROCESS, int $sock_type = SWOOLE_SOCK_TCP);
(2)通過set函數(shù)灸姊,設(shè)置swoole配置
function Server->set(array $setting);
一些set方法的說明:
$serv->set(
????array(
????????'reactor_num' => 2, // 通過此參數(shù)來調(diào)節(jié)Reactor線程的數(shù)量拱燃,以充分利用多核
????????'worker_num' => 4, // 設(shè)置啟動的Worker進程數(shù)量。Swoole采用固定Worker進程的模式
????????'backlog' => 128, // 此參數(shù)將決定最多同時有多少個待accept的連接力惯,swoole本身accept效率是很高的碗誉,基本上不會出現(xiàn)大量排隊情況。
????????'max_request' => 50, // 此參數(shù)表示worker進程在處理完n次請求后結(jié)束運行夯膀。manager會重新創(chuàng)建一個worker進程诗充。此選項用來防止worker進程內(nèi)存溢出。
????????'dispatch_mode' => 1, //1平均分配诱建,2按FD取模固定分配蝴蜓,3搶占式分配,默認(rèn)為取模(dispatch=2)
????)
);
(3)注冊Server的事件回調(diào)函數(shù)on俺猿。
由于swoole是一個異步框架茎匠,里面的很多方法都是通過on函數(shù)綁定,通過回調(diào)進行后續(xù)操作押袍。
bool Server->on(string $event, mixed $callback);
操作的大概流程為:
$serv->on('Connect', 'my_onConnect'); // 監(jiān)聽連接進入事件 诵冒,tcp需要連接,udp不需要連接操作
$serv->on('Receive', 'my_onReceive'); // 監(jiān)聽數(shù)據(jù)接收事件
$serv->on('Close', 'my_onClose'); // 監(jiān)聽連接關(guān)閉事件
(4)啟動服務(wù)
$serv->start();
五谊惭、簡單示例
以上方法的簡單實現(xiàn)示例(摘自官方文檔):
<?php
????//創(chuàng)建Server對象汽馋,監(jiān)聽 127.0.0.1:9501端口
????$serv = new Swoole\Server("127.0.0.1", 9501);
????//監(jiān)聽連接進入事件
????$serv->on('Connect', function ($serv, $fd) { echo "Client: Connect.\n"; });
????//監(jiān)聽數(shù)據(jù)接收事件
????$serv->on('Receive', function ($serv, $fd, $from_id, $data) {
????????????$serv->send($fd, "Server: ".$data);
????});
????//監(jiān)聽連接關(guān)閉事件
????$serv->on('Close', function ($serv, $fd) {
????????echo "Client: Close.\n";
????});
????//啟動服務(wù)器
????$serv->start();
?>
六侮东、udp服務(wù)的簡單示例
tcp和udp服務(wù)雖然都是使用swoole_server服務(wù),但是區(qū)別在于創(chuàng)建一個異步服務(wù)時豹芯,指定模式為UDP:?SWOOLE_SOCK_UDP悄雅。默認(rèn)的模式是SWOOLE_SOCK_TCP。
需要注意的是:UDP服務(wù)器與TCP服務(wù)器不同铁蹈,UDP沒有連接的概念宽闲。啟動Server后,客戶端無需Connect握牧,直接可以向Server監(jiān)聽的9502端口發(fā)送數(shù)據(jù)包容诬。對應(yīng)的事件為onPacket。
//創(chuàng)建Server對象沿腰,監(jiān)聽 127.0.0.1:9502端口览徒,類型為SWOOLE_SOCK_UDP
$serv = new swoole_server("127.0.0.1", 9502, SWOOLE_PROCESS, SWOOLE_SOCK_UDP);
//監(jiān)聽數(shù)據(jù)接收事件
$serv->on('Packet', function ($serv, $data, $clientInfo) {
$serv->sendto($clientInfo['address'], $clientInfo['port'], "Server ".$data);
var_dump($clientInfo);
});
//啟動服務(wù)器
$serv->start();
七、tcp協(xié)議和udp協(xié)議的區(qū)別對比
1矫俺、主要區(qū)別:
(1)TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的吱殉,即發(fā)送數(shù)據(jù)之前不需要建立連接;
(2)TCP提供可靠的服務(wù)厘托。也就是說,通過TCP連接傳送的數(shù)據(jù)稿湿,無差錯铅匹,不丟失,不重復(fù)饺藤,且按序到達(dá);UDP盡最大努力交付包斑,即不保證可靠交付;
TCP通過校驗和涕俗,重傳控制罗丰,序號標(biāo)識,滑動窗口再姑、確認(rèn)應(yīng)答實現(xiàn)可靠傳輸萌抵。如丟包時的重發(fā)控制,還可以對次序亂掉的分包進行順序控制元镀。
(3)UDP具有較好的實時性绍填,工作效率比TCP高,適用于對高速傳輸和實時性有較高的通信或廣播通信栖疑。
(4)每一條TCP連接只能是點到點的;UDP支持一對一讨永,一對多,多對一和多對多的交互通信
(5)TCP對系統(tǒng)資源要求較多遇革,UDP對系統(tǒng)資源要求較少卿闹。
2揭糕、為什么UDP有時比TCP更有優(yōu)勢?
UDP以其簡單、傳輸快的優(yōu)勢锻霎,在越來越多場景下取代了TCP,如實時游戲插佛。
(1)網(wǎng)速的提升給UDP的穩(wěn)定性提供可靠網(wǎng)絡(luò)保障,丟包率很低量窘,如果使用應(yīng)用層重傳雇寇,能夠確保傳輸?shù)目煽啃浴?/p>
(2)TCP為了實現(xiàn)網(wǎng)絡(luò)通信的可靠性,使用了復(fù)雜的擁塞控制算法蚌铜,建立了繁瑣的握手過程锨侯,由于TCP內(nèi)置的系統(tǒng)協(xié)議棧中,極難對其進行改進冬殃。
采用TCP囚痴,一旦發(fā)生丟包,TCP會將后續(xù)的包緩存起來审葬,等前面的包重傳并接收到后再繼續(xù)發(fā)送深滚,延時會越來越大,基于UDP對實時性要求較為嚴(yán)格的情況下涣觉,采用自定義重傳機制痴荐,能夠把丟包產(chǎn)生的延遲降到最低,盡量減少網(wǎng)絡(luò)問題對游戲性造成影響官册。
3生兆、為什么TCP不適用于實時傳輸?
TCP影響實時性不是因為握手消耗時間膝宁。握手一開始建立完就沒事了
一般來說鸦难,單位時間內(nèi)傳輸?shù)臄?shù)據(jù)流量比較平滑。 TCP依賴滑動窗口進行流量控制员淫,滑動窗口大小是自適應(yīng)的合蔽,影響滑動窗口主要有兩個因素,一是網(wǎng)絡(luò)延時介返,二是傳輸速率拴事,滑動窗口的大小與延時成正比,與傳輸速率也成正比映皆。在給定的網(wǎng)絡(luò)環(huán)境下挤聘,延時可以認(rèn)為是固定的春塌,因此滑動窗口僅與傳輸速率有關(guān)谈息,當(dāng)傳輸實時數(shù)據(jù)時,因為數(shù)據(jù)流通量比較固定势决,所以這時TCP上的滑動窗口會處于一個不大不小的固定值步淹,這個值大小恰好保證當(dāng)前生產(chǎn)的數(shù)據(jù)實時傳輸?shù)綄Ψ酱勇。?dāng)出現(xiàn)網(wǎng)絡(luò)丟包時诚撵,按TCP協(xié)議(快速恢復(fù)),滑動窗口將減少到原來的一半键闺,因此速率立刻減半寿烟,此時發(fā)送速率將小于數(shù)據(jù)生產(chǎn)速率,一些數(shù)據(jù)將滯留在發(fā)送端辛燥,然后滑動窗口將不斷增大筛武,直到積累的數(shù)據(jù)全部發(fā)送完畢。上述過程即為典型的TCP流量抖動過程挎塌,對于實時傳輸影響很大徘六,可能形成較大的突發(fā)時延,從用戶感觀角度來說榴都,就是有時比較流暢待锈,但有時卡(“抖一下”,并且比較嚴(yán)重)嘴高,因此實時傳輸通常不使用TCP竿音。
4、udp和tcp可以應(yīng)用的場景:
比如普通的會議視頻圖像拴驮,當(dāng)然首選UDP春瞬,畢竟丟幾包無所謂。
如果傳輸文件等莹汤,不能丟包快鱼,用TCP協(xié)議。
5纲岭、擴展:TCP協(xié)議的三次握手和四次揮手
(1)三次握手
為了準(zhǔn)確無誤的將數(shù)據(jù)發(fā)送到指定IP處,TCP協(xié)議采用了三次握手的策略线罕,如下步驟所示:
①客戶端采用TCP協(xié)議將帶有SYN標(biāo)志的數(shù)據(jù)包發(fā)送給服務(wù)器止潮,等待服務(wù)器的確認(rèn)。
②服務(wù)器端在收到SYN的數(shù)據(jù)包后钞楼,必須確認(rèn)SYN喇闸,即自己發(fā)送的ACK標(biāo)志,同時询件,自己也將會向客戶端發(fā)送一個SYN標(biāo)志燃乍。
③客戶端在接收到服務(wù)器短的SYN+ACK包后,自己會向服務(wù)器發(fā)送ACK包宛琅,完成三次握手刻蟹。那么客戶端和服務(wù)器正式建立了連接,開始傳輸數(shù)據(jù)嘿辟。
三次握手的圖如下所示:
(2)四次揮手
四次揮手是用來斷開服務(wù)器和客戶端之間的通信的舆瘪,之所以要斷開連接片效,是因為TCP/IP 協(xié)議是要占用端口號的,而計算機的端口卻是有限的英古,不進行斷開的話淀衣,勢必會造成計算機資源的浪費。
①在整個通信的過程中召调,誰先發(fā)起請求膨桥,誰就是客戶端。
當(dāng)客戶端的數(shù)據(jù)傳輸?shù)轿膊繒r唠叛,客戶端向服務(wù)器發(fā)送帶有FIN標(biāo)志的數(shù)據(jù)包只嚣,使其明白自己準(zhǔn)備斷開通信了。
②因為TCP的通信是使用全雙工通信的WebSocket玻墅,所以在斷開連接的時候也應(yīng)該是雙向的介牙;當(dāng)服務(wù)器收到帶有FIN標(biāo)志的數(shù)據(jù)包時,其必不會直接發(fā)送FIN標(biāo)志斷開通信的請求澳厢,而是先發(fā)送一個帶有ACK標(biāo)志的應(yīng)答信息环础,使客戶端明白服務(wù)器還有數(shù)據(jù)要進行發(fā)送。
③當(dāng) 服務(wù)器的數(shù)據(jù)發(fā)送完成后剩拢,向客戶端發(fā)送帶有FIN標(biāo)志的數(shù)據(jù)包线得,通知客戶端斷開連接。
④這一次揮手是我覺得四次揮手中設(shè)計的最巧妙的一次徐伐。
當(dāng)客戶端收到FIN后贯钩,擔(dān)心網(wǎng)絡(luò)上某些不可控制的因素導(dǎo)致服務(wù)器不知道他要斷開連接,會發(fā)送ACK進行確認(rèn)办素,同時把自己設(shè)置成TIME_WAIT狀態(tài)并啟動定時器角雷,**在TCP的定時器到達(dá)后客戶端并沒有接收到請求,會重新發(fā)送性穿;當(dāng)服務(wù)器收到請求后就斷開連接勺三;當(dāng)客戶端等待2MLS(兩倍報文最大生存時間)后,沒有收到請求重傳的請求后需曾,客戶端這邊就斷開連接吗坚,**整個TCP通信就結(jié)束了。
四次揮手的圖如下所示: