您好,登錄后才能下訂單哦!
小編給大家分享一下PHP Swoole與TCP的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
1、連接拒絕
2、Operation now in progress 多是因為丟包、錯誤ip、backlog滿了&阻塞&tcp_abort_on_overflow=0
3、min(maxconn, backlog) ss -lt
在TCP三次握手的時候,客戶端發送SYN這個包給服務端,服務端不接受這個請求,操作系統直接返回了一個RST的包,來拒絕連接的請求。
最常見的情況就是客戶端去請求某個服務器,服務端沒有綁定對應的端口。
測試代碼如下,服務端代碼:
<?php $server = new \Swoole\Server('127.0.0.1', 9501); $server->set([ 'work_num' => 2, 'backlog' => 128, ]); $server->on('connect', function ($server, $fd) { echo "Client: Connect.\n"; }); $server->on('receive', function ($server, $fd, $reactor_id, $data) { var_dump($data); }); $server->on('close', function () { var_dump('close'); }); $server->start();
這里,服務端綁定的端口是9501。
啟動服務器:
1 ~/codeDir/phpCode/hyperf-skeleton # php server.php
客戶端代碼:
<?php $client = new \Swoole\Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); var_dump($client->connect('127.0.0.1', 9500));
這里,客戶端請求的端口是9500。
啟動客戶端:
~/codeDir/phpCode/hyperf-skeleton # php client.php Warning: Swoole\Client::connect(): connect to server[127.0.0.1:9500] failed, Error: Connection refused[111] in /root/codeDir/phpCode/hyperf-skeleton/client.php on line 4 bool(false) ~/codeDir/phpCode/hyperf-skeleton #
報錯:
Error: Connection refused[111]
這個錯誤的絕大部分原因是因為連接超時了。
例如路由器、網關出現了故障,包被丟了。
例如客戶端請求了一個錯誤的ip,那么路由器自然也就路由不到。
測試代碼如下,客戶端代碼:
<?php $client = new \Swoole\Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); var_dump($client->connect('8.8.8.8', 9501));
這里,我訪問的是谷歌的DNS服務器。因為我沒有FQ,所以是訪問不了這個IP的。因此,我們發送的包是到達不了8.8.8.8服務器的。
啟動客戶端:
~/codeDir/phpCode/hyperf-skeleton # php client.php Warning: Swoole\Client::connect(): connect to server[8.8.8.8:9501] failed, Error: Operation in progress[115] in /root/codeDir/phpCode/hyperf-skeleton/client.php on line 4 bool(false) ~/codeDir/phpCode/hyperf-skeleton #
報錯:
Error: Operation in progress[115]
服務器在三次握手的最后一次,即收到客戶端發來的ACK包的時候,會把建立好的連接放到backlog隊列里面。如果Swoole一直不accept連接,那么這個backlog隊列很快就會滿。backlog隊列滿了之后,服務端就會丟棄三次握手的SYN包,讓客戶端重新去連接服務端。
測試代碼如下,服務端代碼:
<?php $server = new \Swoole\Server('127.0.0.1', 9501, SWOOLE_BASE); $server->set([ 'work_num' => 2, 'backlog' => 128, ]); $server->on('connect', function ($server, $fd) { echo "Client: Connect.\n"; sleep(1000); }); $server->on('receive', function ($server, $fd, $reactor_id, $data) { var_dump($data); }); $server->on('close', function () { var_dump('close'); }); $server->start();
要想測試backlog問題必須在Swoole的SWOOLE_BASE模式下,默認的SWOOLE_PROCESS模式是沒有這個問題的。
這里,我們的backlog大小是128。
然后,我們通過sleep(1000);來阻塞住進程,使得Swoole不會繼續accept連接,從而導致backlog隊列在某個時刻變滿。
客戶端代碼:
<?php $i = 0; while (true) { $client = new \Swoole\Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); if ($client->connect('127.0.0.1', 9501) == false) { break; } }
我們啟動服務器:
~/codeDir/phpCode/hyperf-skeleton # php server.php
然后啟動客戶端:
~/codeDir/phpCode/hyperf-skeleton # php client.php 省略了其他的輸出 bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) bool(true) Warning: Swoole\Client::connect(): connect to server[127.0.0.1:9501] failed, Error: Operation in progress[115] in /root/codeDir/phpCode/hyperf-skeleton/client.php on line 7 bool(false) Warning: Swoole\Client::connect(): connect to server[127.0.0.1:9501] failed, Error: Operation in progress[115] in /root/codeDir/phpCode/hyperf-skeleton/client.php on line 7 bool(false) ^C ~/codeDir/phpCode/hyperf-skeleton #
我們會發現,過一段時間,客戶端這邊會報錯:
Error: Operation in progress[115]
服務端這邊輸出:
~/codeDir/phpCode/hyperf-skeleton # php server.php
Client: Connect.
因為當Swoole服務器從backlog隊列里面accept一個連接的時候,才會觸發onReceive回調函數。所以,當服務端accept一個連接之后,Swoole自己就會陷入阻塞,不會再accept了。但是需要注意的是,盡管Swoole服務器自身是阻塞的,操作系統還會繼續去把建立好的連接放入backlog隊列里面。所以,backlog隊列會滿。
除了三次握手成功之后會使用到的backlog隊列,還有一個SYN隊列。也就是在三次握手時候,客戶端給服務端發送了SYN包,服務端會有一個SYN隊列來維護。
與其有關的內核配置:
tcp_max_syn_backlog tcp_synack_retries tcp_syncookies
其中,tcp_max_syn_backlog就是這個SYN隊列的長度。如果大量的SYN包把SYN隊列塞滿了,那么其他正常的連接過來,服務端就無法處理。
SYN Flood攻擊就是客戶端瘋狂的給服務端發送SYN包,然后服務端每次都會把請求放到SYN隊列里面。但是,客戶端不給服務端回ACK包。如果客戶端不回ACK包,那么服務端就會給客戶端回SYN + ACK包,即第二次握手發送的包。而回復SYN + ACK包的次數就是由tcp_synack_retries參數決定的。如果把tcp_synack_retries設置為0,那么如果服務端沒有收到ACK包,那么服務端就不會重試發送SYN + ACK包了,這樣就減少了SYN隊列里面那個請求的存活時間。
tcp_syncookies的原理就是,客戶端發送SYN包的時候,不會維護SYN隊列,而是返回一個cookie給客戶端。然后客戶端發送第三次握手的時候,攜帶這個cookie值,只有這個cookie驗證通過,服務端才會給連接分配資源。
php的框架:1、Laravel,Laravel是一款免費并且開源的PHP應用框架。2、Phalcon,Phalcon是運行速度最快的一個PHP框架。3、Symfony,Symfony是一款為Web項目準備的PHP框架。4、Yii,Yii是一款快速、安全和專業的PHP框架。5、CodeIgniter,CodeIgniter是一款非常敏捷的開源PHP框架。6、CakePHP,CakePHP是一款老牌的PHP框架。7.Kohana,Kohana是一款敏捷但是功能強大的PHP框架。
以上是“PHP Swoole與TCP的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。