聊聊分布式架构01——http通信基础

目录

web通信的简单结构

网络通信基础TCP/IP

[TCP/IP 通信传输流](#TCP/IP 通信传输流)

HTTP中的三剑客

负责传输的IP协议

确保可靠性的TCP协议

[SYN攻击(SYN Flood Attack)](#SYN攻击(SYN Flood Attack))

四次挥手

负责域名解析的DNS服务

[基于 TCP 协议实现通信](#基于 TCP 协议实现通信)

[TCP 协议的通信过程](#TCP 协议的通信过程)


Web通信的简单结构

Web 使用一种名为 HTTP(HyperText Transfer Protocol,超文本传输协议)的协议作为规范,完成从客户端到服务器端等一系列运作流程。举个例子,我们使用浏览器访问百度:<www.baidu.com>(Ip:220.181.38.150)。

  1. DNS域名解析:

    DNS(Domain Name System)服务是和HTTP协议一样位于应用层的协议。它提供域名到IP之间的解析服务。

  2. http访问web

网络通信基础TCP/IP

通常使用的网络(包括互联网)是在TCP/IP协议族的基础上运作的。TCP/IP协议族四层结构分为:应用层、传输层、网络层和数据链路层。

  • 应用层:决定了向用户提供应用服务时通信的活动。

  • 传输层:提供处于网络连接中的两台计算机之间的数据传输。常见的是TCP和UDP两种性质不同的协议。

    • TCP(Transmission Control Protocol)

    • UDP(User Data Protocol)

  • 网络层:用来处理在网络上流动的数据包。

  • 链路层(数据链路层、网络接口层):用来处理连接网络的硬件部分。

当然也存在OSI七层机构和TCP/IP五层结构的划分方式。

TCP/IP 通信传输流

发送端在层与层之间传输数据时,每经过一层时必定会被打上一个该层所属的首部信息。反之,接收端在层与层传输数据时,每经过一层时会把对应的首部消去。

HTTP中的三剑客

在TCP/IP协议族中与HTTP密不可分的3个协议:IP协议、TCP协议和DNS协议

负责传输的IP协议

IP 协议的作用是把各种数据包传送给对方。其中两个重要的条件是 IP 地址和 MAC 地址(Media Access Control Address)。IP 地址可以和 MAC 地址进行配对。IP 地址可变换,但 MAC 地址基本上不会更改。

使用ARP协议凭借MAC地址进行通信,这个过程像快递公司的送货过程。寄件人将货物送到集散中心,快递公司根据收件地址就能确定下一站该送往哪个区域的集散中心。这种机制也叫路由选择、
*

确保可靠性的TCP协议

为了准确无误地将数据送达目的地,TCP协议采用了三次握手(three-way handshaking)策略。握手过程中使用了TCP的标志(flag)-SYN(synchronize)和ACK(acknowledgement)。只有三次握手,Client和Server才能相互确认双相连接,实现双工数据传输。

  • 第一次握手(SYN=1,seq=x):客户端发送一个TCP的SYN标志位置1的包,指明要连接的服务器端口以及初始序号x,保存在包头的序列号(Sequence-Number)字段中,发送完毕后,客户端进入SYN-SEND状态。

  • 第二次握手(SYN=1,ACK=1,seq=y,ack=x+1):服务器发回确认包(ACK)应答,即SYN和ACK标志位均为1。服务器将自己ISN(初始序列号)放入Seq中,同时将ack设置为客户端的ISN+1即x+1.发送完毕后,服务器进入SYN-RCVD状态。

  • 第三次握手(ACK=1,seq=x+1,ack=y+1):客户端再次发送确认包(ACK),SYN为0,ACK为1,并且把ack设为服务器的ISN+1即y+1发送给对方,数据发送完毕,客户端进入ESTABLISHED状态,当服务器接收到这个包时,也进入ESTABLISHED状态,TCP握手结束。

SYN攻击(SYN Flood Attack)

是一种网络攻击,通常针对TCP协议的三次握手过程中的漏洞进行攻击。SYN攻击旨在使目标服务器耗尽资源,导致其无法正常处理新的连接请求,从而使服务不可用。以下是SYN攻击的工作原理和防御方法:

工作原理

  1. 攻击者发送大量伪造的TCP连接请求(SYN请求)到目标服务器。

  2. 目标服务器收到这些伪造的连接请求后,会为每个请求分配一些资源,如内存和连接表项,然后回复一个SYN-ACK响应,等待客户端的确认。

  3. 攻击者不回复服务器的SYN-ACK响应,或者回复得很慢,从而使服务器一直等待确认。

  4. 由于服务器需要等待确认,它不断累积未完成的连接请求,消耗了系统资源,最终可能无法再接受新的合法连接请求,导致拒绝服务(DoS)。

防御方法

  1. SYN Cookies:一种常见的防御方法是使用SYN Cookies。在使用SYN Cookies的情况下,服务器不会为每个连接请求分配资源,而是根据客户端的请求生成一个特殊的标识符(SYN Cookie)。只有在客户端回复ACK时,服务器才会分配资源。这可以减轻攻击对服务器资源的影响。

  2. 调整连接资源限制:可以调整服务器的TCP连接资源限制,限制每个IP地址的并发连接数,以减轻攻击的影响。这可以通过操作系统的设置来实现。

  3. 使用防火墙和入侵检测系统(IDS/IPS):防火墙和IDS/IPS可以用于检测和过滤恶意的SYN请求流量。它们可以识别和拦截大规模的SYN攻击尝试。

  4. 网络流量分析:监控和分析网络流量,及时检测异常流量模式,可以帮助发现SYN攻击。

  5. 升级硬件和网络带宽:增加服务器的硬件资源和网络带宽可以增加其抵御SYN攻击的能力,但这并不是解决问题的根本方法。

  6. 使用CDN:使用内容分发网络(CDN)可以分担攻击流量,减轻服务器的负担,提高服务的可用性。

四次挥手

四次挥手的目的是关闭一个连接,连接存在时,客户端和服务器均可主动发起挥手动作(TCP是一个全双工协议),在socket编程中,任何一方执行close()操作即可产生挥手操作。

  • 第一次挥手(FIN=1,seq=u):假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为 1 的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕后,客户端进入 FIN_WAIT_1 状态。

  • 第二次挥手(ACK=1,ack=u+1):服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求, 但还没有准备好关闭连接。发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。

  • 第三次挥手(FIN=1,seq=w):服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为 1。发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。

  • 第四次挥手(ACK=1,ACKnum=w+1):客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT 状态,等待 可能出现的要求重传的 ACK 包。 服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。 客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime) 之后,没有收到服务器端的 ACK,认为服务器端已经正常关闭连接,于是自己也关闭连接, 进入 CLOSED 状态。

为什么连接的时候是三次握手,关闭的时候却是四次握手?

三次握手是因为因为当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。

但是关闭连接时, 当 Server 端收到 FIN 报文时,很可能并不会立即关闭 SOCKET(因为可能还有消息没处理 完),所以只能先回复一个 ACK 报文,告诉 Client 端,"你发的 FIN 报文我收到了"。只有等到 我 Server 端所有的报文都发送完了,我才能发送 FIN 报文,因此不能一起发送。故需要四步握手。
*

负责域名解析的DNS服务

DNS(Domain Name System)服务是和 HTTP 协议一样位于应用层的协议。它提供域名到 IP 地址之间的解析服务。

基于 TCP 协议实现通信

TCP是一个全双工协议,数据通信允许数据同时在两个方向上传输,因此全双工是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。通过Socket简单地模拟下双工通信。

  • server端实现:

    java 复制代码
    public class ServerSocketDemo {
        public static void main(String[] args) throws IOException {
            try {
                ServerSocket server = null;
                // 创建一个serverSocket在端口8080监听客户端请求
                server = new ServerSocket(8080);
                Socket socket = null;
                try {
                    socket = server.accept(); // 使用accept()阻塞等待客户请求
                } catch (IOException e) {
                    e.printStackTrace();
                }
                String line;
                // 由Socket对象得到输入流,并构造响应的BufferedReader对象
                BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    ​
                // 由Socket对象得到输出流,并构造PrintWriter对象
                PrintWriter os = new PrintWriter(socket.getOutputStream());
                // 由系统标准输入设备构造BufferedReader对象
                BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
                // 在标准输出上打印从客户端读入的字符串
                System.out.println("Client:" + is.readLine());
                // 从标准输入读入字符串
                line = sin.readLine(); 
                // 读到"bye"停止循环
                while (!line.equals("bye")) {
                    // 向客户端输出该字符串
                    os.println(line); 
                    // 刷新输出流,使Client马上收到该字符串
                    os.flush();
                    // 在系统标准输出上打印读入的字符串
                    System.out.println("Server:" + line);
                    // 从Client读入字符串,并打印到标准输出上
                    System.out.println("Client:" + is.readLine());
                    // 从系统标准输入读入字符串
                    line = sin.readLine(); 
                }
                os.close();
                is.close();
                socket.close();
                server.close();
            } catch (IOException e) {
                System.out.println("Error:" + e);
            }
        }
    }
  • client端实现:

    java 复制代码
    public class ClientSocketDemo {
        public static void main(String[] args) {
            try {
                // 找到目标serverSocket的地址和端口
                Socket socket = new Socket("localhost", 8080);
    ​
                // 控制台的输入流
                BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
    ​
                // 在当前连接上写入数据
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
    ​
                // 拿到输入流
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    ​
                String readline = sin.readLine();
                while (!readline.equals("bye")) {
                    out.println(readline);
                    out.flush();
                    System.out.println("Client:"+readline);
                    System.out.println("Server:"+in.readLine());
                    readline = sin.readLine(); // 重新获取
                }
                out.close();
                in.close();
                socket.close();
            } catch (IOException e) {
                System.out.println("Error" + e);
            }
        }
    }
TCP 协议的通信过程

首先,对于 TCP 通信来说,每个 TCP Socket 的内核中都有一个发送缓冲区和一个接收缓冲 区,TCP 的全双工的工作模式及 TCP 的滑动窗口就是依赖于这两个独立的 Buffer 和该 Buffer 的填充状态。

缓冲区

接收缓冲区把数据缓存到内核,若应用进程一直没有调用 Socket 的 read 方法进行读取,那么该数据会一直被缓存在接收缓冲区内。不管进程是否读取 Socket,对端发来的数据都会经 过内核接收并缓存到 Socket 的内核接收缓冲区。 read 所要做的工作,就是把内核接收缓冲区中的数据复制到应用层用户的 Buffer 里。 进程调用 Socket 的 send 发送数据的时候,一般情况下是将数据从应用层用户的 Buffer 里复 制到 Socket 的内核发送缓冲区,然后 send 就会在上层返回。换句话说,send 返回时,数据不一定会被发送到对端。

Socket 的接收缓冲区被 TCP 用来缓存网络上收到的数据,一直保存到应用进 程读走为止。如果应用进程一直没有读取,那么 Buffer 满了以后,出现的情况是:通知对端 TCP 协议中的窗口关闭,保证 TCP 接收缓冲区不会移除,保证了 TCP 是可靠传输的。如果对方无视窗口大小发出了超过窗口大小的数据,那么接收方会把这些数据丢弃。

滑动窗口协议

这个过程中涉及到了 TCP 的滑动窗口协议,滑动窗口(Sliding window)是一种流量控制技术。早期的网络通信中,通信双方不会考虑网络的拥挤情况直接发送数据。由于大家不知道 网络拥塞状况,同时发送数据,导致中间节点阻塞掉包,谁也发不了数据,所以就有了滑动窗口机制来解决此问题;发送和接受方都会维护一个数据帧的序列,这个序列被称作窗口。

发送窗口

就是发送端允许连续发送的帧的序号表。 发送端可以不等待应答而连续发送的最大帧数称为发送窗口的尺寸。

接收窗口

接收方允许接收的帧的序号表,凡落在接收窗口内的帧,接收方都必须处理,落在接收窗口外的帧被丢弃。 接收方每次允许接收的帧数称为接收窗口的尺寸。

接收窗口 接收方允许接收的帧的序号表,凡落在接收窗口内的幀,接收方都必须处理,落在接收窗口外的帧被丢弃。 接收方每次允许接收的帧数称为接收窗口的尺寸。

相关推荐
zhao32668575111 分钟前
如何有效利用数据采集HTTP代理
网络·网络协议·http
单片机社区1 小时前
随笔十七、eth0单网卡绑定双ip的问题
网络·嵌入式硬件·网络协议·udp·智能路由器
安静的做,安静的学2 小时前
网络仿真工具Core环境搭建
linux·网络·网络协议
会飞的爱迪生3 小时前
http跳转https
网络协议·http·https
Fireworkitte4 小时前
HTTPS的加密原理
网络协议·http·https
JavaPub-rodert4 小时前
如何给自己的域名配置免费的HTTPS How to configure free HTTPS for your domain name
网络协议·http·https
小度爱学习4 小时前
数据链路层协议
运维·服务器·网络·网络协议·网络安全
jimiStephen6 小时前
ZooKeeper 数据模型
分布式·zookeeper·云原生
Ciderw6 小时前
TCP三次握手和四次挥手
开发语言·网络·c++·后端·网络协议·tcp/ip·golang
翻晒时光8 小时前
设计模式:春招面试的关键知识储备
分布式·面试·职场和发展