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

news2024/11/24 9:51:45

目录

web通信的简单结构

网络通信基础TCP/IP

TCP/IP 通信传输流

HTTP中的三剑客

负责传输的IP协议

确保可靠性的TCP协议

SYN攻击(SYN Flood Attack)

四次挥手

负责域名解析的DNS服务

基于 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端实现:

    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端实现:

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

发送窗口

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

接收窗口

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1069239.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【面试经典150 | 哈希表】赎金信

文章目录 写在前面Tag题目来源题目解读解题思路方法一:哈希表方法二:数组模拟哈希表 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带…

Node.js代码漏洞扫描工具介绍——npm audit

npm audit 运行安全检查 主要作用:检查命令将项目中配置的依赖项的描述提交到默认注册中心,并要求报告已知漏洞。如果发现任何漏洞,则将计算影响和适当的补救措施。如果 fix 提供了参数,则将对包树应用补救措施。 具体参考&#x…

php 安装mongodb扩展模块,rdkafka模块

mongodb mongodb扩展下载 选择php版本,根据报错提示,选择扩展对应的版本选择非安全进程将php_mongodb.dll放到php/ext目录下修改php.ini配置,添加extensionphp_mongodb.dll开启php_mongodb扩展,重启服务php -m 查看是否开启成功…

vue3 -- ts封装 Turf.js地图常用方法

Turf.js中文网 地理空间分析库,处理各种地图算法 文档地址 安装 Turf 库 npm install @turf/turf创建src/hooks/useTurf.ts 文件1:获取线中心点 效果: 代码: useTurf.ts import * as turf from @turf/turf// 获取线中心点 export class CenterPointOfLine {

使用springboot服务端远程调试? 试试HTTP实现服务监听

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《初阶数据结构》《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 wi…

ws升级为wss

需求:项目中需要使用netty,本地测试的时候使用的是ws,然后要部署到服务器上,使用https连接,https下就不能用ws了,必须升级到wss 1.阿里云申请免费证书 2.保存证书到本地目录 3.修改代码 SslUtil 工具类…

kt6368A双模蓝牙芯片无法透传 可能是什么问题呢

一、问题简介- kt6368A蓝牙芯片无法透传 可能是什么问题呢? KT6368A蓝牙芯片,在使用上还是非常的简单,总共也就8个腿,焊接也是很容易的事情 出现不能透传,大概率有如下2点原因 硬件问题,比如&#xff1…

学习笔记|串口通信的基础知识|同步/异步|RS232|常见的串口软件的参数|STC32G单片机视频开发教程(冲哥)|第二十集:串口通信基础

目录 1.串口通信的基础知识串口通信(Serial Communication)同步/异步?全双工?常见的串口软件的参数 2.STC32的串口通信实现原理引脚选择:实现分时复用模式选择串口1模式1,模式1波特率计算公式 3.串口通信代码实现编写串口1通信程序…

C++深入学习part_2

面向对象思想 这一节Java里面都有类似的概念,比较简单,就不写的太啰嗦了。 首先是认识以前面向过程的思想: 而现在再来感受一下面向对象的思想: 这玩意儿学过Java的话应该是比较简单的,就不再赘述了。 类的定义 代…

数据安全防护:云访问安全代理(CASB)

云访问安全代理(Cloud Access Security Broker,CASB),是一款面向应用的数据防护服务,基于免应用开发改造的配置方式,提供数据加密、数据脱敏功能。数据加密支持国密算法,提供面向服务侧的字段级…

玄子Share- IDEA 2023 Web 热部署

玄子Share- IDEA 2023 热部署 添加热部署依赖 普通 Web 项目使用热部署插件需指定版本 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><version>3.1.3</version><!-…

nrm 安装教程(图文教程)

序&#xff1a; 1、都知道nvm解决的是node版本切换的问题&#xff0c;nrm 解决的是则是npm指向的问题。 2、雪狼的公众号&#xff1a;“程序员野区”&#xff0c;也许未来的莫一天&#xff0c;你会用到&#xff0c;不凡先进来瞅瞅公众号都分享了啥内容 正文&#xff1a; 1、安…

vue3+elementPlus:el-select选择器里添加按钮button

vue3elementPlus&#xff1a;el-select选择器里添加按钮button&#xff0c;在el-select的option后面添加button //html <el-select class"selectIcon" value-key"id" v-model"store.state.HeaderfilterText" multiple collapse-tagscollapse-…

力扣(LeetCode)2034. 股票价格波动(C++)

哈希表有序集合 请看本题解的分析&#xff1a; 题目的关键是四大操作&#xff0c;其中 current/maximum/minimum 明示我们&#xff0c;数据流应有快速找到一些数据的能力&#xff1a; 时间戳最大的股票所对应的价格&#xff0c;即题目所定义的最新股票价格在当前数据流节点&a…

Headless CMS(strapi)

Headless CMS(strapi) 玩了玩微信小程序的cms&#xff0c;感觉还挺好的&#xff0c;不过目前处于公测阶段&#xff0c;后续应该还是要收费的&#xff0c;不过这个操作还挺好的。文档地址 不过其获取图片的时候默认用到的是小城云开发环境的链接样式&#xff0c;如果用在公开网…

【Zookeeper专题】Zookeeper经典应用场景实战(二)

目录 前置知识课程内容一、Zookeeper分布式锁实战1.1 什么是分布式锁1.2 基于数据库设计思路1.3 基于Zookeeper设计思路一1.4 基于Zookeeper设计思路二1.5 Curator 可重入分布式锁工作流程1.6 总结 二、基于Zookeeper实现服务的注册与发现2.1 设计思路2.2 Zookeeper实现注册中心…

聊聊分布式架构04——RPC通信原理

目录 RPC通信的基本原理 RPC结构 手撸简陋版RPC 知识点梳理 1.Socket套接字通信机制 2.通信过程的序列化与反序列化 3.动态代理 4.反射 思维流程梳理 码起来 服务端时序图 服务端—Api与Provider模块 客户端时序图 RPC通信的基本原理 RPC&#xff08;Remote Proc…

算法通过村第十二关-字符串|黄金笔记|冲刺难题

文章目录 前言最长公共前缀纵向比较横向比较 字符串压缩问题表示数值的字符串总结 前言 提示&#xff1a;我有时候在想&#xff0c;我是真的不太需要其他人&#xff0c;还是因为跟他们在一起时没法自己&#xff0c;所以才保持距离。我们的交谈就像是平行而毫无交集的自言自语。…

高压功率放大器是什么东西

高压功率放大器是一种电子设备&#xff0c;用于将低功率信号放大到高功率水平。它通常由多个功率放大器组成&#xff0c;可以处理来自各种信号源的输入信号&#xff0c;并输出具有更大功率的信号。 高压功率放大器广泛应用于许多领域&#xff0c;包括无线通信、广播、雷达、医学…

Pytorch-学习记录-1-Tensor

1. 张量 (Tensor): 数学中指的是多维数组&#xff1b; torch.Tensor data: 被封装的 Tensor dtype: 张量的数据类型 shape: 张量的形状 device: 张量所在的设备&#xff0c;GPU/CPU requires_grad: 指示是否需要计算梯度 grad: data 的梯度 grad_fn: 创建 Tensor 的 Functio…