您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)Swoole中怎么搭建TCP服務(wù),小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
通過Swoole可以快速創(chuàng)建一個TCP服務(wù),新建一個文件命名為 tcp_server.php,代碼如下:
在命令行執(zhí)行如下命令就可以開啟TCP服務(wù):
php tcp_server.php
運行完命令后就可以通過 netstat 工具查看服務(wù)是否啟動成功,如果已經(jīng)在監(jiān)聽9501端口了,這時就可以使用 telnet/netcat 工具來連接服務(wù)器了。
telnet 127.0.0.1 9501
helloServer: hello
netstat工具使用方法:netstat -an | grep 9501
代碼邏輯分析:
通過以上代碼就可以創(chuàng)建一個TCP服務(wù),監(jiān)聽的端口是9501。它的邏輯很簡單,當(dāng)客戶端$socket通過網(wǎng)絡(luò)發(fā)送一個hello字符串時,服務(wù)器端會回復(fù)一個Server:hello字符串。
Server是異步服務(wù)器,所以是同過監(jiān)聽事件的方式來編寫程序的。當(dāng)對應(yīng)的事件發(fā)生時,底層會主動回調(diào)指定的函數(shù)。如當(dāng)有洗的TCP連接金額入時,會執(zhí)行 onConnect 事件回調(diào),當(dāng)某個連接向服務(wù)器發(fā)送數(shù)據(jù)時會回調(diào) onReceive 函數(shù)。
注意事項:
服務(wù)器可以同時被成千上萬個客戶端連接,$fd 就是客戶端連接的唯一標(biāo)識符
Receive 事件的回調(diào)函數(shù)中 $from_id 為線程ID
調(diào)用 $srver->send() 方法向客戶端連接發(fā)送數(shù)據(jù),參數(shù)就是 $fd 柯達(dá)護(hù)短標(biāo)識符
調(diào)用 $server->close() 方法可以強制關(guān)閉某個客戶端連接
客戶端可能會主動斷開連接,此時會觸發(fā) onClose 事件回調(diào)
無法連接到服務(wù)器的簡單檢測手段:
在linux下,使用 netstat -an | grep 端口,查看端口是否已經(jīng)被打開處于Listening狀態(tài)
上一步確認(rèn)后,再檢查防火墻問題
注意服務(wù)器所用的IP地址,如果是127.0.0.1回環(huán)地址,則客戶端只能使用127.0.0.1才能連接上
用的阿里云服務(wù)器或者騰訊云服務(wù)器,需要再安全權(quán)限組進(jìn)行設(shè)置開發(fā)的端口
TCP服務(wù)已經(jīng)啟動,下面我們要用Swoole搭建TCP客戶端來連接TCP服務(wù)。新建一個文件,命名為 tcp_client.php,代碼如下:
上面代碼創(chuàng)建了一個TCP的同步客戶端,此客戶端用于連接 server.php 開啟的TCP服務(wù)。向服務(wù)端發(fā)送一個 hello world 字符串,服務(wù)器會返回一個 Server:hello world 字符串。
在命令行運行如下命令就可以連接TCP服務(wù):
php tcp_client.php
Server:hello world
這個客戶端是同步阻塞的,connect/send/recv 會等待IO完成后再返回。同步阻塞操作并不消耗CPU資源。當(dāng)IO操作未完成時,當(dāng)前進(jìn)程會自動轉(zhuǎn)入 sleep 模式。當(dāng)IO完成后,操作系統(tǒng)會喚醒當(dāng)前進(jìn)程,繼續(xù)向下執(zhí)行代碼。
流程如下:
TCP需要進(jìn)行3次握手,所以connect至少需要3次網(wǎng)絡(luò)傳輸過程
在發(fā)送少量數(shù)據(jù)時,$client->send 都是可以立即返回的。發(fā)送大量數(shù)據(jù)時,socket 緩沖區(qū)可能會塞滿,send 操作會阻塞。
recv 操作會阻塞等待服務(wù)器返回數(shù)據(jù),recv 耗時等于服務(wù)器處理時間+網(wǎng)絡(luò)傳輸耗時之和。
TCP客戶端還有一種異步非阻塞的實現(xiàn)形式。使用異步模式時,connect 會理解返回 true。但實際上連接并未建立。這時不能在 connect 后立即使用 send 發(fā)送數(shù)據(jù),需要先通過isConnected() 判斷是否連接成功。當(dāng)連接成功后,系統(tǒng)會自動回調(diào) onConnect 函數(shù)。這時才可以使用 send 函數(shù)向服務(wù)器發(fā)送數(shù)據(jù)。
通過上面的代碼我們就實現(xiàn)了TCP服務(wù)端和客戶端,當(dāng)服務(wù)端和客戶端建立TCP連接后,如何維持連接不斷開呢?下面我們將介紹一下基于Swoole搭建的TCP服務(wù)器心跳維持方案。
正常情況下客戶端中斷TCP連接時,會發(fā)送一個FIN包,進(jìn)行4次斷開握手來通知服務(wù)器。但一些異常情況下,如客戶端突然斷電斷網(wǎng)或者網(wǎng)絡(luò)異常,服務(wù)器可能無法得知客戶端已斷開連接。尤其是異動網(wǎng)絡(luò),TCP連接非常不穩(wěn)定,所以需要一套機制來保證服務(wù)器和客戶端之間的連接的有效性。
Swoole擴展本身內(nèi)置了這種機制,開發(fā)者只需要配置一個參數(shù)即可啟用。Swool在每次收到客戶端數(shù)據(jù)會記錄一個時間戳,當(dāng)客戶端在一定時間內(nèi)未向服務(wù)器端發(fā)送數(shù)據(jù),那服務(wù)器會自動切斷連接。
配置方法如下:
上面的設(shè)置就是每5秒偵測一次心跳,一個TCP連接如果再10秒內(nèi)未向服務(wù)器發(fā)送數(shù)據(jù),連接將會被切斷。
通過以上案例我們對Swoole的事件驅(qū)動模型有了一定的了解。下面我們將詳細(xì)介紹Swoole的回調(diào)事件。
事件執(zhí)行順序
所有事件回調(diào)均在 $server->start 后發(fā)生
服務(wù)器關(guān)閉程序終止時最后一次事件是 onShutdown
服務(wù)器啟動成功后,onStart /onManagerStart / onWorkerStart 會在不同的進(jìn)程內(nèi)并發(fā)執(zhí)行
onReceive / onConnect / onClose 在 Worker 進(jìn)程中觸發(fā)
Worker / Task 進(jìn)程啟動/結(jié)束時會分別調(diào)用一次 onWorkerStart / onWorkerStop
onTask 事件僅在 task 進(jìn)程中發(fā)生onFinish 事件僅在 Worker進(jìn)程中發(fā)生
以上就是Swoole中怎么搭建TCP服務(wù),小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。