PHP:Swoole与TCP三次握手_八重樱。的博客-程序员秘密

技术标签: 程序员  swoole  php  php高级  IT  

握手常见问题

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

启动服务器:

~/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]

Operation now in progress

这个错误的绝大部分原因是因为连接超时了。

丢包

例如路由器、网关出现了故障,包被丢了。

错误ip

例如客户端请求了一个错误的ip,那么路由器自然也就路由不到。

测试代码如下,客户端代码:

<?php
​
$client = new \Swoole\Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);
var_dump($client->connect('8.8.8.8', 9501));

这里,我访问的是谷歌的DNS服务器。因为我没有翻墙,所以是访问不了这个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]

backlog

服务器在三次握手的最后一次,即收到客户端发来的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问题必须在SwooleSWOOLE_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队列会满。

SYN Flood

除了三次握手成功之后会使用到的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验证通过,服务端才会给连接分配资源。

 

更多swoole的知识可以加入(点击→)我的官方群677079770

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43814458/article/details/102842007

智能推荐

Appium+python自动化23-Android夜神模拟器操作app(2)_夜神 appactivity_crazyBird_GJY的博客-程序员秘密

前言 前面两篇环境已经搭建好了,接下来就是需要启动APP,如何启动app呢?首先要获取包名,然后获取launcherActivity。获取这两个关键东西的方法很多,这里就不一一多说,小伙伴们可以各显神通。小编这里主要给大家推荐一个sdk自带的实用工具aapt. aapt即Android Asset Packaging Tool,在SDK的build-tools目录下。该工具可以查...

七夕,程序员教你5个表白代码,2分钟学会,牢牢主抓她的心_表白代码编程教学_一见已难忘的博客-程序员秘密

情人节。一个有人欢喜有人愁的节日,虽然对一些单身人士不太友好,但还有不少人都在等这个节日进行表白。毕竟这个日子的成功率会高一些。情人节少不了送花送礼物,作为一个程序员,当然不会在送什么礼物上给你指点一二,但可以发挥自己的优势,给需要的朋友分享几个浪漫的表白方式,只需要在电脑上敲几行代码即可,而且十分简单,一看就会。如果暂时用不到的也可以先收藏起来,以后用得着的时候能找到。从简单到复杂先拿出这5个。先来2个不需要代码的简单方式1、最简单的Ctrl+f这个是利用的网页查找功能,在网页中打开这些字,因为

信息系统安全与对抗实践慕课笔记 -- Linux基础_信息系统安全和对抗实践._绀香零八的博客-程序员秘密

虚拟机的使用虚拟化的定义虚拟化,是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在-台计算机_上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的利用效率。用户在逻辑计算机上的操作体验如同真实的计算机。虚拟化的类型虚拟化的用途企业用户:将整台服务器划分为若干个小的服务器以便于对资源、权限管理互联网...

2016年计算机一级excel试题及答案,2016年计算机一级试题加答案_屋顶长颈鹿的博客-程序员秘密

2016年计算机一级试题加答案计算机一级主要考核微型计算机基础知识和使用办公软件及因特网(Internet)的基本技能。接下来为大家提供关于计算机一级考试题及答案,希望能帮助到各位考生!一、判断正误题(共25题,每题1分)1、若要把A4单元格中的89000改为89780,只要单击该单元格,在其中插入光标,并将其插入点移至9后面,按两次Del键后删除数字9后面的两个0,然后输入数字78,按回车键后确...

coredump配置、产生原理、分析及示例_dylan_zhouhailiang的博客-程序员秘密

coredump配置、产生、分析以及分析示例关键词:coredump、core_pattern、coredump_filter等等。应用程序在运行过程中由于各种异常或者bug导致退出,在满足一定条件下产生一个core文件。通常core文件包含了程序运行时内存、寄存器状态、堆栈指针、内存管理信息以及函数调用堆栈信息。core就是程序当前工作转改存储生成的一个文件,通过工具分析这个文件,可以定位到程序异常退出的时候对应的堆栈调用等信息,找出问题点并解决。配置coredump如果需要使用需要通过ul

软件开发技术:国际化(globalization )_lxguru2的博客-程序员秘密

如果你的潜在客户可能来自其它国家,代码的国际化就是一个必须适当处理的问题。源代码的大部是编程语言语法认可的关键词,操作符等。源代码使用的自定义变量/函数/类/名字空间等,应避免使用非英文字母。需要注意国际化的,是代码使用的文本资源,文字格式,货币/日期格式。文本资源尽量采用UNICODE 编码方式。格式化字符串/货币/日期时,要区分用户显示有关或无关情况。若与用户显示有关,应按照用户选

随便推点

智能门锁电路图_智能门锁结构拆解,我们一起来看看_万基酱的博客-程序员秘密

智能门锁给我们居家更加安全、更加方便。那么它到底是又什么结构组成的呢?我们一起来看看智能门锁结构拆解。第一:电子部分1、指纹头智能锁的指纹头,主要分两种,光学指纹头和半导体指纹头。一般来说,半导体指纹头价格会高于光学指纹头,但是有些识别点数多的光学指纹头会比低档的半导体指纹头贵。2、马达马达是为智能锁提供动力的电机,是电子与机械的连接设备,力量的转换中枢,起着承上启下的重大作用。当用密码或者刷卡、...

php7 wamp启动失败,配置wamp环境出现Apache无法启动的问题(一个Apache上安装多个版本PHP)..._Actor.又戈叔的博客-程序员秘密

问题:使用Apache2.4配置php7.0.6和php7.2.1,php7.0.6可以启动,而php7.2.1无法启动。httpd.conf配置参数如下:LoadModule php7_module "C:/php7.0.6/php7apache2_4.dll"PHPIniDir "C:/php7.0.6"LoadModule php7_module "C:/php7.2.1/php7apach...

JS实现动态的日期选择表单_netleaf的博客-程序员秘密

JS实现动态的日期选择表单,使用方法:  showDateSelect("date1")其中参数为表单项select的名称,然后可以用date1.value获取选择的日期.  动态的日期选择表单 function yearList(num){ var d=new Date(); var t=d.getFullYear(); var yStr=""; for(var i=t-num;

Makefile 之 include_include到父makefile_namecyf的博客-程序员秘密

本节我们讨论如何在一个 Makefile 中包含其它的 makefile 文件。Makefile 中包含其它文件的关键字是“include”,和 C 语言对头文件的包含方式一致。    “include”指示符告诉 make 暂停读取当前的 Makefile,而转去读取“include”指定的一个或者多个文件,完成以后再继续当前 Makefile 的读取。Makefile 中指示符

基于ArcGIS开发3D立方体空间关系判断_zLulus的博客-程序员秘密

本文基于ArcGIS Runtime SDK for .NET(100.9.0),官方有2D的资料Spatial relationships,本文完成三维的立方体是否相交的判定,效果如图[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JWXnIrxF-1606466099992)(https://img2020.cnblogs.com/blog/942899/202011/942899-20201109143035221-1991025870.gif)]实现思路地图初始化

Microsoft Visual Studio 2010(vs2010) 中文版安装_weixin_30653023的博客-程序员秘密

Microsoft Visual Studio 2010(vs2010) 中文版安装日期:2019-05-12 时间:20:03:36 编辑:张国富下载地址基本简介Microsoft Visual Studio(vs2010是简称)是微软公司推出的开发环境。visual studio 2010支持网页开发和应用程序开发。vs...

推荐文章

热门文章

相关标签