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。
启动服务器:
~/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问题必须在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队列会满。
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验证通过,服务端才会给连接分配资源。
PHP Swoole与TCP三次握手的更多相关文章
- TCP三次握手/四次挥手详解
一. TCP/IP协议族 TCP/IP是一个协议族,通常分不同层次进行开发,每个层次负责不同的通信功能.包含以下四个层次: 1. 链路层,也称作数据链路层或者网络接口层,通常包括操作系统中的设备驱动程 ...
- wireshark抓包工具简介以及tcp三次握手的一些含义
wireshark是非常流行的网络封包分析软件,功能十分强大.可以截取各种网络封包,显示网络封包的详细信息.使用wireshark的人必须了解网络协议,否则就看不懂wireshark了.为了安全考虑, ...
- TCP三次握手四次挥手
看到一篇总结很好的TCP三次握手,学习一下,原文链接. 建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,S ...
- TCP ,UDP概念和TCP三次握手连接 的知识点总结
OSI 计算机网络7层模型 TCP/IP四层网络模型 传输层提供应用间的逻辑通信(端到端),网络层提供的是主机到主机的通信,传输层提供的是可靠服务. TCP 中常说的握手指的是:连接的定义和连接的建立 ...
- Wireshark基本介绍和学习TCP三次握手
wireshark介绍 wireshark的官方下载网站: http://www.wireshark.org/ wireshark是非常流行的网络封包分析软件,功能十分强大.可以截取各种网络封包,显示 ...
- TCP 三次握手四次挥手, ack 报文的大小.tcp和udp的不同之处、tcp如何保证可靠的、tcp滑动窗口解释
一.TCP三次握手和四次挥手,ACK报文的大小 首先连接需要三次握手,释放连接需要四次挥手 然后看一下连接的具体请求: [注意]中断连接端可以是Client端,也可以是Server端. [注意] 在T ...
- iOS 开发:TCP三次握手连接
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握 ...
- 用tcpdump分析tcp三次握手,四次挥手
1.tcpdump 简介 tcpdump是一个对网络上的数据包进行截获的包分析工具,一般linux系统以命令的形式使用 2.tcp三次握手 建立一个tcp连接会发生下面三个过程: 1.服务器必须准备好 ...
- TCP三次握手,数据传输,四次挥手
TCP包结构 一个TCP包结构如下: 一个TCP包主要由TCP包头和数据部分组成,包头固定部分为20字节,选项和数据部分根据实际情况设置为4N(N可以为0)字节. 1.16bit源端口和目的端口号,它 ...
随机推荐
- 3步轻松搞定Spring Boot缓存
作者:谭朝红 前言 本次内容主要介绍基于Ehcache 3.0来快速实现Spring Boot应用程序的数据缓存功能.在Spring Boot应用程序中,我们可以通过Spring Caching来快速 ...
- 《Java基础知识》序列化与反序列化详解
序列化的作用:为了不同jvm之间共享实例对象的一种解决方案.由java提供此机制. 序列化应用场景: 1. 分布式传递对象. 2. 网络传递对象. 3. tomcat关闭以后会把session对象序列 ...
- Django forms组件里的ChoiceField、ModelChoiceField和ModelMutipleChoiceField的区别
阅读简要 首先我们要明白Django forms组件里的ChoiceField.ModelChoiceField和ModelMutipleChoiceField是继承关系 ChoiceField 1. ...
- C# -- DateTime与TimeSpan
1. DateTime的使用 DateTime dt = DateTime.Now; StringBuilder sb = new StringBuilder(); sb.AppendLine(str ...
- 微信小程序—支付宝身份验证(支付宝小程序)
查看应用:https://open.alipay.com/platform/keyManage.htm 这里找到您调用接口的应用 支付宝身份验证快速接入:https://docs.open.alip ...
- Linux中环境变量相关文件的区别
Linux下各种不同环境变量相关文件的作用: 1. /etc/environment 设置整个系统的环境,系统启动时,该文件被执行. 2. /etc/profile 设置所有用户的环境,当用 ...
- Redis学习(二)Redis的安装
Window 下安装 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你系统平台的实际情况选择 ...
- weblogic启动服务器Authentication denied: Boot identity not valid
新分配的测试服务器,已经安装好了weblogic,使用命令nohub ./startWeblogic.sh启动weblogic没有问题 登录控制台,点击环境-服务器-新建,一步步完成后,点击部署.选择 ...
- php 将科学计算法得出的结果转换成原始数据 NumToStr
由于php最大只支持显示 15位因的数据运算,大于15位的2数加减乘除的数据的结果,会直接用科学计数法显示, 但在现实生活中,科学计数法不利于普通人识别,所以,本函数将:科学计数法的出的结果转换成原始 ...
- 在cnetos7上搭建mysql主从服务
本文主要是介绍在centos上搭建mysql的主从服务器.如果没有搭建过的,可以查看我以前的博客,里面有详细的安装centos和在centos上安装mysql的说明. 一.安装从虚拟机: 1.右键—& ...