草庐IT

详解TCP原理

陌上 烟雨齐 2023-10-29 原文

目录

前言

TCP协议

TCP协议的格式

TCP原理

1、确认应答

2、超时重传

3、连接管理

4、滑动窗口

5、流量控制

6、拥塞控制

7、延时应答

8、捎带应答

9、面向字节流

10、异常情况

总结


前言

TCP协议是一种传输层协议,也是TCP/IP协议栈中非常重要的一个协议,它提供了面向连接,可靠性传输,面向字节流等特性。使传输的效率和可靠性大大提高。可靠性是TCP协议的最核心的机制。它可以在数据传输时提供各种控制和错误恢复机制,确保数据在网络中可靠传输。

TCP协议

TCP,即Transmission Control Protocol,传输控制协议。人如其名,要对数据的传输进行一个详细的控制。

TCP协议的格式

 可以看出TCP的报文格式还是比UDP比较复杂的。

  • 源端口 : 和UDP的源端口一致,标识数据从那个进程来的。
  • 目的端口 :标识数据要到那个进程中去。
  • 32位序号:用于标识数据从发送方发送到接收方的字节流。
  • 32位确认序号:只有当接收方给发送方返回ack时,确认序号才有用。表示接收方希望发送方发送下一编号的字节数据。
  • 4位首部长度:占用4位,以4个字节为单位计算。标识TCP的头部有多少个4字节。标识TCP头部的长度。固定长度为20个字节。
  • 保留6位:不做讨论。
  • 6个标志位:占用6位,包含URG、ACK、PSH、RST、SYN和FIN等标志位,分别表示紧急数据、确认、推送数据、重置连接、同步序列号和结束连接等功能。
  • 16位窗口大小:表示接收方可以接收的数据量的大小。
  • 16位的校验和:用于检测数据的完整性,包括TCP的报头和数据部分。
  • 16位紧急指针:当URG为1时,标识那部分数据是紧急数据。

上述就是TCP报文的报头结构。

下面进行详细的介绍。

TCP原理

TCP对数据传输的管控机制,主要在两个方面,一是效率,而是安全,保证在数据传输安全的前提下,尽可能的提高传输效率。

1、确认应答

实现可靠性最核心的机制。

TCP发送方将每个字节的数据进行编号,即为序号。

接收端在接收到这个带有序号的数据之后,就进行发送ack报文,这个ack报文里面带有接收端给发送方的确认序号,确认序号就是从接收到的数据中最后一个字节序号的下一个序号,就是告诉发送端,我已经收到了你发的数据,下一次你从哪里开始发送。

在网络中由于网络的原因,有可能会有后发先至的情况。

在发送方发送的数据中,由于是TCP是对每一个字节进行编号的,在网络传输的过程中,可能有某个字节因为网络不稳定的原因延迟到达,其他字节已经在TCP的接收缓冲区中了,这是数据就会产生紊乱。但是因为TCP的序号的作用,可以针对序号在接收缓冲区中进行排序,使数据变得有序。这样上层的应用层就不会读到错误的数据了。

2、超时重传

如果网络稳定,数据也没有产生错误,那么数据就很顺利的发送并接收,但是如果网络在发送数据的时候,因为某个结点出了问题,这样数据就不能发送到接收端了,就会产生丢包问题。

丢包之后,接收端肯定就收不到数据,就不能发送ack确认报文。

此时发送方就在等接收方给它的确认报文,等待一段时间之后,还是没有收到接收方发来的确认报文,发送方就会视为刚才发送的数据丢包了,就会进行重发。

如果说发送的数据接收端收到了,但是接收端发送的ack丢包了,发送方也就等不到ack报文了。

发送方也是一样在等待一定的时间之后,如果还是没有ack报文,那么发送方就认为数据丢包了,此时发送方就会再次发送一次之前发送的数据。

上述过程客户端B就会接收到重复的数据,但是TCP协议因为序号的存在,是能够帮我们自动识别出哪些是重复数据,并且把重复的数据丢弃。

如果有多个数据都丢包了,那么TCP会继续进行超时重传,但是每丢包一次,超时重传的时间就变长了,也就说重传的频率变低了。

如果多次重传,都没有得到ack回应,那么TCP就会尝试重置连接,如果重置连接也失效,那么TCP此时就之间断开连接。

TCP实现可靠性是由确认连接和超时重传实现的。

3、连接管理

建立连接 :三次握手

握手:是通信双方建立一次网络交互,相当于客户端和服务器之间通过三次交互,互相建立了连接关系(双方各自记录对方的信息)。

 syn为同步报文段 :其本质就是要和对方申请建立一个连接。

ack为确认报文段。

客户端A在给客户端B发送一个syn表示要和客户端B建立连接,此时客户端B也想和客户端A建立连接,于是客户端B就给客户端A发送了一个syn+ack报文,表示我同意和你建立连接,但是你也得和我建立连接,此时客户端A收到之后,欣然应允,于是就发送了一个ack确认报文。

至此客户端A和客户端B就经过上述的三次握手之后,就正式的建立起来了连接。

 在我们的TCP报头中,有这6个特殊的bit位,默认为0,当SYN字段为1时,就表示是一个SYN报文,当ACK字段为1时,就表示是一个ACK报文,当他们两个全部为1时,就表示是一个syn+ack报文。

那么为什么需要三次握手呢?

三次握手这个过程,其实就是在检测通信双方的发送能力和接收能力是否正常,是后续进行数据可靠传输的基础。

断开连接:四次挥手

四次挥手和三次握手是非常相似的。

通信双方,各自给对方发送一个FIN(结束报文),然后在各自给对方返回一个ack报文。

 在三次握手中syn和ack是合并成一个数据包进行发送的,但是在四次挥手这里,通常情况下是不能合并的。

因为三次握手的syn和ack是在同一时机触发的(由系统内核触发的)。

四次挥手这里FIN和ACK的触发时机是不同的,ACK是由系统内核触发的,在收到FIN报文的第一时间就返回ACK报文。但是FIN是由应用程序代码控制的,在调用socket的close方法时,就会触发FIN报文。

不能合并就在于你的代码逻辑是咋样的,是在发现客户端A断开连接之后,客户端B这边立马进行close操作,那么就触发了第二个FIN,如果这是ACK报文还没有发出去,那么就可以合并,如果在发现对方断开连接之后,不是立马进行close操作,如果是中间还隔了很久,那么就不能合并。

需要注意的是连接是由系统内核进行维护的,如果某个进程结束了,但是内核还是会维护TCP的连接,直到完成四次挥手。

FIN报文就是当FIN字段为1时,就表示此报文就是一个FIN报文。

4、滑动窗口

滑动窗口,也叫批量传输

上述的确认应答机制是对每发送的一个数据报,都要等待一个ack确认报文,收到ack确认报文之后在发下一个数据报,但是这样的话性能就较差。

滑动窗口就是一次发送多个数据报,就可以大大提高性能。

批量不是无限发送,是发送到一定的程度,就等待ack,不等待ack就能发送的数据报是有限制的,这个限制就是窗口大小。

而且是批量发送完成之后,返回一个ack就立即发送下一条。

上图中批量发送4条数据,发完之后,统一等待ack,注意是每收到一个ack之后,就发送下一条数据,不是等收到4个ack之后在发下一组。

上述批量传输的过程就是滑动窗口。

 窗口的大小就是指无需等待ack就能发送的数据报的最大值。上图就是400个字节,4个段。

发送前4个段的时候,无需等待ack就能直接发送数据,等收到第一个ack之后,窗口向后滑动,继续发送第五个数据段。操作系统为了维护这个窗口,需要开辟一个发送缓冲区来记录当前还有哪些数据没有应答,只有确认应答过的数据,才能从发送缓冲区中删除掉。

图1中批量发送了4条数据,图1中的白色区域,相当于是等待ack的应答。

图2中当主机B给主机A返回一个ack之后,说明1001-2000已经收到,此时就会发送5001-6000的数据。

可以看到窗口是向后挪动了一个格子,如果此时收到的ack报文速度非常快,那么这个窗口就会快速的向后挪动。这也就是滑动窗口的由来。

如果在批量发送的过程中出现丢包之后,滑动窗口的处理机制也是非常灵活的。

TCP协议一定是先保证可靠性,其次才是效率。

如果出现丢包,无外乎2种情况:

数据在发送的过程中丢了

可以看到数据1001-2000在发送的过程丢了,接收方会一直向发送方索要1001-2000的数据,当发送方连续收到3个同样的索要1001的ack时,发送方就反应过来1001-2000是丢了,就会重新发送1001-2000这个数据,当发送方把1001-2000这个数据发送过去之后,接收方返回的确认ack是7001 ,而不是2001,因为此时7001之前的数据已经发送过来了,全部在接收方接收缓冲区中。

上述的重传过程没有任何的冗余,只有发送没有接收的数据,不会有重复发送的情况。整体的速度是比较的快的。也被称为快速重传

数据已经抵达,但是确认ack丢了

 这个情况其实在TCP中是没有必要担心的,因为确认序号的原因,后一个ack能覆盖前一个ack,也就说当当收到2001的ack时,发送方就已经知道2001之间的数据是成功接收到的。

如果是最后一个ack丢了,其实也没有事情,这时TCP的超时重传就会起作用。在等待一段时间之后,如果没有ack报文出现,就会重新发送最后一个的数据。

5、流量控制

流量控制也是TCP中的一个安全机制。

接收端所能接受的数据是有限的,如果发送端发送的太快,导致瞬间就填满了接收端的接收缓冲区之后,后面发来的数据接收端就会直接丢弃。

流量控制就是通过控制发送方的发送速度,来解决上述问题。

 在ack携带的报文中,有16位的窗口大小这个字段,这里的值就是建议发送端发送的窗口大小。

接收方计算窗口大小是非常简单粗暴的,是直接拿剩余的接收缓冲区中的大小作为窗口大小。

 从上图就可以看出,当发送方第一次接收到接收方的ack时,此时接收方的窗口大小是已经在ack报文中携带了,也就说接收方剩余的接收缓冲区大小为3000,于是发送方就按照这个大小进行批量发送,当发送到接收方缓冲区大小为0时,就停止发送,因为接收方的接收缓冲区已经满了,此时发送方就会每隔一段时间发送一个窗口探测报文,如果探测一会发现接收方的剩余空间不是0了,此时就可以继续发送。当接收端剩余空间腾出来了之后,也会发送各一个窗口更新通知,通知发送方按照这个窗口大小进行发送。

6、拥塞控制

滑动窗口的大小取决于流量控制和拥塞控制。

流量控制衡量了接收端的处理能力。拥塞控制衡量了传输路径的处理能力。

如果网络当前就很拥堵,此时要是贸然的发送大量的数据,就会造成数据和网络的同时损失。

因为网络上有很多的结点,拥塞控制就是衡量中间路径,中间路径上有多少个结点,每个结点的当前情况。

TCP引入 慢启动 机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据。

开始的时候,先按照一个非常小的发送速率进行发送,如果不丢包,就扩大发送速率(窗口大小),如果出现丢包,就立即把速率降小。

然后重复上述的过程。

 可以看出来上述的拥塞窗口的增长速度是非常快的。是指数级别的增长。

 可以看到刚开始传输是按照一个非常小的阈值进行发送,然后在按照指数增长的的速度进行发送,短时间让窗口大小达到一个比较大的值。

指数增长到达了一定阈值 ssthresh,就会变成线性增长,避免拥塞。

当增长到一定的程度,出现了网络拥塞,就认为此时的窗口大小已经到了当前网络的传输上限了,然后立即把窗口大小调整为较小的初始值,然后重复上述过程。

7、延时应答

保证TCP可靠性的核心是确认应答。

ack是一定要发的,但是不是立刻就发送ack报文,而是磨蹭会在发送,因为TCP中决定发送效率的是窗口大小,窗口大小就是接收方的接收缓冲区剩余大小。如果是等会在回复ack报文的话,那么此时应用程序可能会消费一些数据,消费数据之后,接收缓冲区中就把消费的数据删除了,这样接收缓冲区中大小就会变大,窗口大小也会变大。下次就能发送更多的数据过来。

延时应答的效果就是通过延时发送ack报文,让接收方的应用程序更可能的多消费一些数据,此时返回的窗口大小就会大一点。发送方发送的速度也会快一点。同时也能满足让接收方能处理过来。

8、捎带应答

基于延时应答。

客户端和服务器之间的通信模式是一问一答的形式的。

在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 "一发一收" 的。意味着客户端给服务器说了 "How are you",服务器也会给客户端回一个 "Fine, thank you";
那么这个时候ACK就可以搭顺风车,和服务器回应的 "Fine,thank you" 一起回给客户端
合并为一个包比分成两个包发送是效率较高的。

9、面向字节流

粘包问题

当发送端给接收端发送多个数据之后,这些数据全部都在接收端的接收缓冲区中,紧紧的挨在一起,此时接收端读数据的时候,就难以区分从哪里到哪里是一个完整的数据,就会导致读出半个包/一个半包的情况出现。

此时我们可以定义个一个分隔符来区分数据包。

package netWork.netWork02;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoServer {
    //serverSocket 就是在外场拉客的
    //ClientSocket 就是服务于拉来的客人的
    //serverSocket 只有一个,但是clientSocket会给每个客户端都分配一个
    private ServerSocket serverSocket = null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);  //进行端口号绑定
    }
    public void start() throws IOException {
        //还可以使用线程池的方式
        ExecutorService executorService = Executors.newCachedThreadPool();
        System.out.println("服务器启动!!!");
        while (true) {
            //accept()   接收一个连接   clientSocket 针对具体的客户端进行服务  通过这个clientSocket和客户端进行通信
            Socket clientSocket = serverSocket.accept();  //accept是会阻塞的,如果没有客户端连接的话,就会阻塞

            //频繁的创建和销毁线程对系统资源的消耗也是很大的
            /*如果直接调用这个方法,会影响这个循环的二次执行。到时accept就不及时了,
            采用创建新的线程来调用processConnection这个方法
            每次来一个新的客户端都创建一个新的线程
            主线程就是while循环,只做两件事,accept 和创建线程,当线程创建好了之后,就下一次调用accept,
            刚刚创建好的线程,去处理请求
            处理连接和处理请求之间是并发的,没有关联关系*/
           /* Thread t = new Thread(()->{
                try {
                    processConnection(clientSocket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            t.start();*///这个循环和线程中的任务就会并发的执行

            //使用线程池的方式
            //一个连接的所有请求处理完,这个线程不会立即销毁,而是放在线程池里面,下次直接使用。
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
    //通过这个方法来处理一个连接
    //读取请求
    //根据请求计算响应
    //把响应返回给客户端
    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress().toString(),
                clientSocket.getPort());
        //通过clientSocket拿到一对Stream对象,inputStream 输入,从网卡读
        //outputStream 输出,往网卡写
        try(InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream()){
            //把inputStream和outputStream进行包装
            Scanner scanner = new Scanner(inputStream);
            PrintWriter printWriter = new PrintWriter(outputStream);
            while (true) {
                // 1 读取请求
                if(!scanner.hasNext()) {
                    System.out.printf("[%s:%d] 客户端下线\n",clientSocket.getInetAddress().toString(),
                            clientSocket.getPort());
                    break;  //读取的流到结尾了,没有数据了,(对端关闭连接了)
                }
                //直接使用scanner来读取一段字符串 使用换行来区分数据包
                String request = scanner.next();

                // 2  根据请求计算响应
                String response = process(request);

                // 3  把响应写回客户端  响应也是要带上换行的
                printWriter.println(response);
                printWriter.flush();  //刷新缓存区   冲刷   数据立即写入网卡中
                System.out.printf("[%s:%d] req: %s,resp: %s\n",clientSocket.getInetAddress().toString(),
                        clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            clientSocket.close();  //只给一个连接提供服务的,时刻都有新的连接,所有要释放
        }
    }
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer = new TcpEchoServer(9090);
        tcpEchoServer.start();
    }
}

可以看出在上述的TCP服务器代码中我们就是使用分隔符来区分的。

还可以约定长度来区分数据包。

这两个解决方案都是在我们的代码是自己定义实现的。

10、异常情况

进程终止:进程终止会释放文件描述符,仍然可以发送FIN。和正常关闭没有什么区别。连接是在操作系统内核中维护的。
机器重启:和进程终止的情况相同。
机器掉电/网线断开:接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行reset。即使没有写入操作,TCP自己也内置了一个保活定时器,会定期询问对方是否还在。如果对方不在,也会把连接释放。

总结

TCP之所以这么复杂,就在于TCP既想要提高传输可靠性,又尽可能的保证传输的效率。

可靠性:

  • 校验和
  • 序列号(按序到达)
  • 确认应答
  • 超时重发
  • 连接管理
  • 流量控制
  • 拥塞控制

提高效率:

  • 滑动窗口
  • 快速重传
  • 延迟应答
  • 捎带应答

有关详解TCP原理的更多相关文章

  1. 物联网MQTT协议详解 - 2

    一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su

  2. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

  3. 【Unity游戏破解】外挂原理分析 - 2

    文章目录认识unity打包目录结构游戏逆向流程Unity游戏攻击面可被攻击原因mono的打包建议方案锁血飞天无限金币攻击力翻倍以上统称内存挂透视自瞄压枪瞬移内购破解Unity游戏防御开发时注意数据安全接入第三方反作弊系统外挂检测思路狠人自爆实战查看目录结构用il2cppdumper例子2-森林whoishe后记认识unity打包目录结构dll一般很大,因为里面是所有的游戏功能编译成的二进制码游戏逆向流程开发人员代码被编译打包到GameAssembly.dll中使用il2ppDumper工具,并借助游戏名_Data\il2cpp_data\Metadata\global-metadata.dat

  4. 【详解】Docker安装Elasticsearch7.16.1集群 - 2

    开门见山|拉取镜像dockerpullelasticsearch:7.16.1|配置存放的目录#存放配置文件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/config#存放数据的文件夹mkdir-p/opt/docker/elasticsearch/node-1/data#存放运行日志的文件夹mkdir-p/opt/docker/elasticsearch/node-1/log#存放IK分词插件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/plugins若你使用了moba,直接右键新建即可如上图所示依次类推创建

  5. 【Elasticsearch基础】Elasticsearch索引、文档以及映射操作详解 - 2

    文章目录概念索引相关操作创建索引更新副本查看索引删除索引索引的打开与关闭收缩索引索引别名查询索引别名文档相关操作新建文档查询文档更新文档删除文档映射相关操作查询文档映射创建静态映射创建索引并添加映射概念es中有三个概念要清楚,分别为索引、映射和文档(不用死记硬背,大概有个印象就可以)索引可理解为MySQL数据库;映射可理解为MySQL的表结构;文档可理解为MySQL表中的每行数据静态映射和动态映射上面已经介绍了,映射可理解为MySQL的表结构,在MySQL中,向表中插入数据是需要先创建表结构的;但在es中不必这样,可以直接插入文档,es可以根据插入的文档(数据),动态的创建映射(表结构),这就

  6. 计算机网络笔记:TCP三次握手和四次挥手过程 - 2

    TCP是面向连接的协议,连接的建立和释放是每一次面向连接的通信中必不可少的过程。TCP连接的管理就是使连接的建立和释放都能正常地进行。三次握手TCP连接的建立—三次握手建立TCP连接①若主机A中运行了一个客户进程,当它需要主机B的服务时,就发起TCP连接请求,并在所发送的分段中用SYN=1表示连接请求,并产生一个随机发送序号x,如果连接成功,A将以x作为其发送序号的初始值:seq=x。主机B收到A的连接请求报文,就完成了第一次握手。客户端发送SYN=1表示连接请求客户端发送一个随机发送序号x,如果连接成功,A将以x作为其发送序号的初始值:seq=x②主机B如果同意建立连接,则向主机A发送确认报

  7. 最强Http缓存策略之强缓存和协商缓存的详解与应用实例 - 2

    HTTP缓存是指浏览器或者代理服务器将已经请求过的资源保存到本地,以便下次请求时能够直接从缓存中获取资源,从而减少网络请求次数,提高网页的加载速度和用户体验。缓存分为强缓存和协商缓存两种模式。一.强缓存强缓存是指浏览器直接从本地缓存中获取资源,而不需要向web服务器发出网络请求。这是因为浏览器在第一次请求资源时,服务器会在响应头中添加相关缓存的响应头,以表明该资源的缓存策略。常见的强缓存响应头如下所述:Cache-ControlCache-Control响应头是用于控制强制缓存和协商缓存的缓存策略。该响应头中的指令如下:max-age:指定该资源在本地缓存的最长有效时间,以秒为单位。例如:Ca

  8. IDEA 2022 创建 Spring Boot 项目详解 - 2

    如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1.  创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1.  创建SpringBoot项目        打开IDEA,选择NewProject创建项目。        填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。        选择springboot版本以及需要的包,此处只选择了springweb。        此处需特别注意,若你使用的是jdk1

  9. 详解Unity中的粒子系统Particle System (二) - 2

    前言上一篇我们简要讲述了粒子系统是什么,如何添加,以及基本模块的介绍,以及对于曲线和颜色编辑器的讲解。从本篇开始,我们将按照模块结构讲解下去,本篇主要讲粒子系统的主模块,该模块主要是控制粒子的初始状态和全局属性的,以下是关于该模块的介绍,请大家指正。目录前言本系列提要一、粒子系统主模块1.阅读前注意事项2.参考图3.参数讲解DurationLoopingPrewarmStartDelayStartLifetimeStartSpeed3DStartSizeStartSize3DStartRotationStartRotationFlipRotationStartColorGravityModif

  10. Slowloris DoS攻击的原理与简单实现 - 2

    前言    Slowloris攻击是我在李华峰老师的书——《MetasploitWeb 渗透测试实战》里面看的,感觉既简单又使用,现在这种攻击是很容易被防护的啦。不过我也不敢真刀实战的去试,只是拿个靶机玩玩罢了。         废话还是写在结语里面吧。(划掉)结语可以不看(划掉)Slowloris攻击的原理        Slowloris是一种资源消耗类DoS攻击,它利用部分HTTP请求进行操作。也叫做慢速攻击,这里的慢速并不是说发动攻击慢,而是访问一条链接的速度慢。Slowloris攻击的功能是打开与目标Web服务器的连接,然后尽可能长时间的保持这些连接打开。如果由多台电脑同时发起Slo

随机推荐