四大常见的网络协议详解,超详细的介绍,工作面试必备!!!

MQTT

协议特点

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是**一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议,该协议构建于TCP/IP协议上**,由IBM在1999年发布。

MQTT最大优点在于,用极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。

作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

MQTT 与 HTTP 一样,MQTT 运行在传输控制协议/互联网协议 (TCP/IP) 堆栈之上。

这是一种消息传递模式,消息不是直接从发送器发送到接收器(即点对点),而是由MQTT server(或称为 MQTT Broker)分发的。

架构

服务器分发消息,因此必须是发布者,但绝不是订阅者!

客户端可以发布消息(发送方)、订阅消息(接收方)或两者兼而有之。

客户端(也称为节点)是一种智能设备,如微控制器或具有 TCP/IP 堆栈和实现 MQTT 协议的软件的计算机。

Qos (Quality of Service levels)

服务质量是 MQTT 的一个重要特性。**用于定义消息传递的可靠性和保证交付的等级。**这些级别在发布时使用。如果客户端发布到 MQTT 服务器,则客户端将是发送者,MQTT 服务器将是接收者。当MQTT服务器向客户端发布消息时,服务器是发送者,客户端是接收者。

  1. QoS 0(最多一次):消息发送者将消息发送给订阅者后,不会收到关于消息是否成功发送和接收的确认。这是最不可靠的级别,因为消息可能会丢失或重复。
  2. QoS 1(至少一次):消息发送者会确保消息至少被接收一次。发送者会持续发送消息,直到接收到 订阅者的确认消息(PUBACK)。如果发送者没有收到确认消息,则会尝试重新发送消息,直到确认为止。
  3. QoS 2(只有一次)消息发送者会确保消息仅被接收一次,且按照发送顺序进行发送者和接收者都会进行握手过程来保证消息的可靠性。QoS 2级别是最可靠、最耗费资源的级别,在需要确保消息不丢失和不重复的场景下使用。

三元组

使用三元组 : ProductKey(产品),DeviceName(设备名),DeviceSecret(设备密钥) 创建一个唯一的设备.

产品组里面的Topic列表里面有一个${deviceName}的设备名称的替换. , 在设备组里面就真正的进行替换了.

在这里插入图片描述

发送回复机制

set方法订阅对应设备的一个开关方法. APP发布开关操作事件 , 阿里云服务器就会监听到 , 然后转发给设备.

用户想开空调 , 打开APP , 点击开, 发送命令给阿里云 , 阿里云服务器转发给设备 .

设备调用post方法将结果返回给阿里云服务器, 阿里云服务器返回给APP. 确保命令正确执行

报文结构

  1. 固定头部(Fixed Header):固定头部在每个报文中都存在,并包含了必要的控制信息。它的字节长度为 1 至 5 字节,具体长度取决于报文类型和一些属性。固定头部包括以下字段:
    • 报文类型(Message Type):用于标识报文类型的枚举值。
    • 标志位(Flags):用于表示报文的一些标志和控制选项,具体取决于报文类型。
    • 剩余长度(Remaining Length):指示了报文剩余部分的长度,以字节为单位。
  2. 可变头部(Variable Header):根据不同报文类型的需要,可变头部可能会包含一些特定的字段。其长度和内容也会根据报文类型的不同而有所变化。可变头部是可选的,某些报文类型可能不包含可变头部。
  3. 报文有效载荷(Payload):报文有效载荷包含实际的数据内容。它的格式和内容根据不同的报文类型而有所不同。例如,在发布消息(PUBLISH)报文中,有效载荷是要发布的消息内容;在订阅请求(SUBSCRIBE)报文中,有效载荷是要订阅的主题等。

报文

在这里插入图片描述

HTTP

OSI七层协议

  1. 物理层(Physical Layer):
    • Ethernet:一种广泛使用的有线局域网(LAN)协议,定义了电缆、连接器和信号传输规范。
    • Wi-Fi:一种无线局域网(WLAN)协议,用于在无线环境中传输数据。
    • USB(Universal Serial Bus):一种用于连接计算机和外部设备的通用串行总线标准。
  2. 数据链路层(Data Link Layer):
    • PPP(Point-to-Point Protocol):一种用于建立点对点连接的协议,通常用于拨号上网和虚拟专用网络(VPN)等场景。
    • Ethernet:在物理层基础上实现的局域网协议,提供了可靠的数据传输和错误检测功能。
    • HDLC(High-level Data Link Control):一种数据链路协议,常用于广域网(WAN)中的数据传输。
  3. 网络层(Network Layer):
    • IP(Internet Protocol):一种用于在网络上标识和定位设备的协议,负责将数据包从源地址传输到目标地址。
    • ICMP(Internet Control Message Protocol):用于在 IP 网络上传输控制消息的协议,例如 ping 和 traceroute。
    • ARP(Address Resolution Protocol):用于将 IP 地址解析为 MAC 地址的协议,常用于局域网中的设备通信。
  4. 传输层(Transport Layer):
    • TCP(Transmission Control Protocol):提供可靠、面向连接的数据传输,确保数据按顺序到达目标设备。
    • UDP(User Datagram Protocol):提供无连接的数据传输,适用于实时性要求高的应用,如音频和视频传输。
  5. 会话层(Session Layer):
    • SSL/TLS(Secure Sockets Layer/Transport Layer Security):提供安全的通信机制,用于加密和认证网络会话。
    • NetBIOS(Network Basic Input/Output System):在局域网中处理会话和命名服务的协议。
  6. 表示层(Presentation Layer):
    • ASCII(American Standard Code for Information Interchange):一种常用的字符编码标准,用于在计算机之间交换文本信息。
    • JPEG(Joint Photographic Experts Group):一种常用的图像压缩格式,用于存储和传输图像数据。
  7. 应用层(Application Layer):
    • HTTP(Hypertext Transfer Protocol):用于在 Web 浏览器和服务器之间传输超文本的协议。
    • FTP(File Transfer Protocol):用于在客户端和服务器之间进行文件传输的协议。
    • DNS(Domain Name System):用于将域名解析为 IP 地址的协议,使得用户可以通过域名访问网站。

在这里插入图片描述

TCP/IP模型

TCP/IP 是一种网络协议族,它定义了在 Internet 上进行通信的一系列规则和协议。TCP/IP 模型是一个四层的协议栈,包括以下层次:

  1. 应用层:负责处理应用程序之间的通信和数据交换。常见的应用层协议有 HTTP、FTP、SMTP、DNS 等。
  2. 传输层:提供端到端的可靠数据传输和错误处理。常见的传输层协议有 TCP(传输控制协议)和 UDP(用户数据报协议)。
  3. 网络层:负责将数据包从源地址传输到目标地址,并处理路由选择和逻辑寻址。常见的网络层协议有 IP(网际协议)。
  4. 链路层:负责在物理网络中传输数据帧。它包括了与物理介质相关的细节,如以太网、Wi-Fi、PPP(点对点协议)等。

以下是 TCP/IP 模型涉及的一些协议和技术:

  • 应用层协议:HTTP、FTP、SMTP、DNS、Telnet、SSH、SNMP 等。
  • 传输层协议:TCP、UDP。
  • 网络层协议:IP(IPv4 和 IPv6)、ICMP(Internet 控制消息协议)、ARP(地址解析协议)、OSPF(开放最短路径优先)、BGP(边界网关协议)等。
  • 链路层协议:以太网(Ethernet)、Wi-Fi、PPP、MAC(介质访问控制)等。
  • 网络地址转换技术:NAT(网络地址转换)。
  • 路由协议:RIP(路由信息协议)、OSPF、BGP 等。

需要注意的是,TCP/IP 模型中的每一层都有自己对应的协议和功能,这些协议共同组成了 Internet 的基础架构。不同的应用程序和网络设备在不同的层次上使用这些协议来实现网络通信。

程序员眼中的层次

只分为程序层(Tomc), 和内核层.

在这里插入图片描述

三次握手

使用tcpdump 抓包

在这里插入图片描述

socket

socket顾名思义就是[套接字]的意思,用于**描述地址和端口,是一个通信链的句柄**。应用程序通过socket向网络发出请求或者回应。

Linux当中, 一个socket对应一个文件描述符., 位于传输层和应用层之间.

是一个四元组 , IPA: port 1 —> IPB: port 2 , port的最大个数是65535个, 所以一个IP 到另一个IP可以建立65535个连接

其实服务端只需要消耗80端口号就行了, 服务端需要消耗65535个端口号, 主要是利用了四元组保证连接 唯一性.

在这里插入图片描述

HTTP

超文本传输协议可以进行文字分割:超文本(Hypertext)、传输(Transfer)、协议(Protocol)

  1. 超文本:

    在互联网早期的时候,我们输入的信息只能保存在本地,无法和其他电脑进行交互。我们**保存的信息通常都以文本即简单字符的形式存在,文本是一种能够被计算机解析的有意义的二进制数据包。而随着互联网的高速发展,两台电脑之间能够进行数据的传输后,人们不满足只能在两台电脑之间传输文字,还想要传输图片、音频、视频,甚至点击文字或图片能够进行超链接的跳转,那么文本的语义就被扩大了,这种语义扩大后的文本就被称为超文本(Hypertext)**。

  2. 传输:

    我们存储的**超文本会被解析成为二进制数据包,由传输载体(例如同轴电缆,电话线,光缆)负责把二进制数据包由计算机终端传输到另一个终端的过程**称为传输(transfer)

  3. 协议 :

    网络协议就是网络中(包括互联网)传递、管理信息的一些规范。如同人与人之间相互交流是需要遵循一定的规矩一样,计算机之间的相互通信需要共同遵守一定的规则,这些规则就称为网络协议。

HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范

浏览器

浏览器是使用 HTTP 协议的主要载体,

我们在地址栏输入URL(即网址),浏览器会向DNS(域名服务器,后面会说)提供网址由它来完成 URL 到 IP 地址的映射。然后将请求**你的请求提交给具体的服务器,在由服务器返回我们要的结果以HTML编码格式返回给浏览器),浏览器执行HTML编码,将结果显示在浏览器的正文**。这就是一个浏览器发起请求和接受响应的过程。

CDN

CDN的全称是==Content Delivery Network,即内容分发网络==,它**应用了 HTTP 协议里的缓存和代理技术,代替源站响应客户端的请求。CDN 是构建在现有网络基础之上的网络,它依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。**CDN的关键技术主要有内容存储和分发技术。

打比方说你要去亚马逊上买书,之前你只能通过购物网站购买后从美国发货过海关等重重关卡送到你的家里,现在在中国建立一个亚马逊分基地,你就不用通过美国进行邮寄,从中国就能把书尽快给你送到。

超文本标记语言

HTML 称为超文本标记语言,是一种标识性的语言。它**包括一系列标签.通过这些标签可以将网络上的文档格式统一,使分散的 Internet 资源连接为一个逻辑整体。**HTML 文本是由 HTML 命令组成的描述性文本,HTML 命令可以说明文字,图形、动画、声音、表格、链接等。

TCP/IP

TCP/IP 协议你一定听过,TCP/IP 我们一般称之为协议簇,什么意思呢?就是 TCP/IP 协议簇中不仅仅只有 TCP 协议和 IP 协议,它是一系列网络通信协议的统称。而其中最核心的两个协议就是 TCP / IP 协议,其他的还有 UDP、ICMP、ARP 等等,共同构成了一个复杂但有层次的协议栈。

TCP 协议的全称是 Transmission Control Protocol 的缩写,意思是传输控制协议,HTTP 使用 TCP 作为通信协议,这是因为 TCP 是一种可靠的协议,而可靠能保证数据不丢失。

**IP 协议的全称是 Internet Protocol 的缩写,它主要解决的是通信双方寻址的问题。**IP 协议使用 IP 地址 来标识互联网上的每一台计算机,可以把 IP 地址想象成为你手机的电话号码,你要与他人通话必须先要知道他人的手机号码,计算机网络中信息交换必须先要知道对方的 IP 地址。(关于 TCP 和 IP 更多的讨论我们会在后面详解)

DNS

你有没有想过为什么你可以通过键入 www.google.com 就能够获取你想要的网站?我们上面说到,计算机网络中的每个端系统都有一个 IP 地址存在,而把 IP 地址转换为便于人类记忆的协议就是 DNS 协议。

DNS 的全称是域名系统(Domain Name System,缩写:DNS),它作为**将域名和 IP 地址相互映射的一个分布式数据库**,能够使人更方便地访问互联网。

URI / URL

URI的全称是(Uniform Resource Identifier),中文名称是统一资源标识符,使用它就能够唯一地标记互联网上资源。

URL的全称是(Uniform Resource Locator),中文名称是统一资源定位符,也就是我们俗称的网址,它实际上是 URI 的一个子集。

URI 不仅包括 URL,还包括 URN(统一资源名称)

在这里插入图片描述

HTTPS

HTTP 一般是明文传输,很容易被攻击者窃取重要信息,鉴于此,HTTPS 应运而生。==HTTPS 的全称为 (Hyper Text Transfer Protocol over SecureSocket Layer),全称有点长,HTTPS 和 HTTP 有很大的不同在于 HTTPS 是以安全为目标的 HTTP 通道,在 HTTP 的基础上通过传输加密和身份认证保证了传输过程的安全性。==HTTPS 在 HTTP 的基础上增加了 SSL 层,也就是说 HTTPS = HTTP + SSL。(这块我们后面也会详谈 HTTPS)

HTTP 请求响应过程

你是不是很好奇,当你在浏览器中输入网址后,到底发生了什么事情?你想要的内容是如何展现出来的?让我们通过一个例子来探讨一下,我们假设访问的 URL 地址为 http://www.someSchool.edu/someDepartment/home.index,当我们输入网址并点击回车时,浏览器内部会进行如下操作:

  1. DNS服务器会首先进行域名的映射,找到访问www.someSchool.edu所在的地址,然后HTTP 客户端进程在 80 端口发起一个到服务器 www.someSchool.edu 的 TCP 连接(80 端口是 HTTP 的默认端口)。在**客户和服务器进程中都会有一个套接字与其相连**。
  2. HTTP 客户端通过它的套接字向服务器发送一个 HTTP 请求报文。该报文中包含了路径 someDepartment/home.index 的资源,我们后面会详细讨论 HTTP 请求报文。
  3. HTTP 服务器通过它的套接字接受该报文,进行请求的解析工作,并**从其存储器(RAM 或磁盘)中检索出对象** www.someSchool.edu/someDepartment/home.index,然后**把检索出来的对象进行封装,封装到 HTTP 响应报文中,并通过套接字向客户进行发送。**
  4. HTTP 服务器随即通知 TCP 断开 TCP 连接,实际上是需要等到客户接受完响应报文后才会断开 TCP 连接。
  5. HTTP 客户端接受完响应报文后,TCP 连接会关闭。HTTP 客户端从响应中提取出报文中是一个 HTML 响应文件,并检查该 HTML 文件,然后循环检查报文中其他内部对象。
  6. 检查完成后,HTTP 客户端会把对应的资源通过显示器呈现给用户。

HTTP请求特征

从上面整个过程中我们可以总结出 HTTP 进行分组传输是具有以下特征

  1. 支持客户-服务器模式 , C/S模式
  2. 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有 GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。
  3. 灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。
  4. 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  5. **无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。**缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

请求路径

http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument

  1. http:

    http://告诉浏览器使用何种协议。对于大部分 Web 资源,通常使用 HTTP 协议或其安全版本,HTTPS 协议。另外,浏览器也知道如何处理其他协议。例如, mailto: 协议指示浏览器打开邮件客户端;ftp:协议指示浏览器处理文件传输。

  2. www.example.com :

    www.example.com 既是一个域名,也代表管理该域名的机构。它指示了需要向网络上的哪一台主机发起请求。当然,也可以直接向主机的 IP address 地址发起请求。但直接使用 IP 地址的场景并不常见。

  3. 80 :

    两个主机之间要发起 TCP 连接需要两个条件,主机 + 端口。它表示用于访问 Web 服务器上资源的入口。如果访问的该 Web 服务器使用HTTP协议的标准端口(HTTP为80,HTTPS为443)授予对其资源的访问权限,则通常省略此部分。否则端口就是 URI 必须的部分。

  4. 路径

    /path/to/myfile.html 是 Web 服务器上资源的路径。以端口后面的第一个 / 开始,到 ? 号之前结束,中间的 每一个/ 都代表了层级(上下级)关系。这个 URL 的请求资源是一个 html 页面

  5. 查询参数

    ?key1=value1&key2=value2 是提供给 Web 服务器的额外参数。如果是 GET 请求,一般带有请求 URL 参数,如果是 POST 请求,则不会在路径后面直接加参数。这些参数是用 & 符号分隔的键/值对列表。key1 = value1 是第一对,key2 = value2 是第二对参数

  6. 锚点

    #SomewhereInTheDocument 是**资源本身的某一部分的一个锚点。锚点代表资源内的一种“书签”,它给予浏览器显示位于该“加书签”点的内容的指示。 例如,在HTML文档上,浏览器将滚动到定义锚点的那个点上;在视频或音频文档上,浏览器将转到锚点代表的那个时间。值得注意的是 # 号后面的部分,也称为片段标识符,永远不会与请求一起发送到服务器。**

HTTP报文格式

HTTP 协议主要由三大部分组成:

  • 起始行(start line):描述请求或响应的基本信息;
  • 头部字段(header):使用 key-value 形式更详细地说明报文;
  • 消息正文(entity)实际传输的数据,它不一定是纯文本,可以是图片、视频等二进制数据。

其中**起始行头部字段成为 请求头 或者 响应头统称为 Header消息正文也叫做实体,称为 bodyHTTP 协议规定每次发送的报文必须要有 Header,但是可以没有 body,也就是说头信息是必须的,实体信息可以没有**。而且在 header 和 body 之间必须要有一个空行

在这里插入图片描述

在这里插入图片描述

起始行

每个报文的起始行都是由三个字段组成:方法、URL 字段和 HTTP 版本字段。

在这里插入图片描述

HTTP 请求方法一般分为 8 种,它们分别是

  1. GET 获取资源,GET 方法用来请求访问已被 URI 识别的资源。指定的资源经服务器端解析后返回响应内容。也就是说,如果请求的资源是文本,那就保持原样返回;

  2. POST 传输实体,虽然 GET 方法也可以传输主体信息,但是便于区分,我们一般不用 GET 传输实体信息,反而使用 POST 传输实体信息,

  3. PUT 传输文件,PUT 方法用来传输文件。就像 FTP 协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求 URI 指定的位置。

    但是,鉴于 HTTP 的 PUT 方法自身不带验证机制,任何人都可以上传文件 , 存在安全性问题,因此一般的 W eb 网站不使用该方法。若配合 W eb 应用程序的验证机制,或架构设计采用REST(REpresentational State Transfer,表征状态转移)标准的同类 Web 网站,就可能会开放使用 PUT 方法。

  4. HEAD 获得响应首部,HEAD 方法和 GET 方法一样,只是不返回报文主体部分。用于确认 URI 的有效性及资源更新的日期时间等。

  5. DELETE 删除文件,DELETE 方法用来删除文件,是与 PUT 相反的方法。DELETE 方法按请求 URI 删除指定的资源。

  6. OPTIONS 询问支持的方法,OPTIONS 方法用来查询针对请求 URI 指定的资源支持的方法。

  7. TRACE 追踪路径,TRACE 方法是让 Web 服务器端将之前的请求通信环回给客户端的方法。

  8. CONNECT 要求用隧道协议连接代理CONNECT 方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行 TCP 通信主要使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加 密后经网络隧道传输。

请求头

http://www.someSchool.edu/someDepartment/home.index, 来看一下它的请求头部

Host: www.someschool.edu
Connection: close
User-agent: Mozilla/5.0
Accept-language: fr
  1. Host: www.someschool.edu : 这个首部行提供的信息是 Web 代理高速缓存所需要的
  2. Connection: close : 表示的是浏览器需要**告诉服务器使用的是非持久连接**。它要求服务器在发送完响应的对象后就关闭连接。
  3. User-agent: **这是请求头用来告诉 Web 服务器,浏览器使用的类型**是 Mozilla/5.0,即 Firefox 浏览器。
  4. Accept-language: 告诉 Web 服务器,浏览器想要得到对象的法语版本,前提是服务器需要支持法语类型,否则将会发送服务器的默认版本

响应状态码

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Keep-Alive

Keep-Alive 有两个参数,它们是以逗号分隔的参数列表,每个参数由一个标识符和一个由等号 = 分隔的值组成。

timeout:指示空闲连接必须保持打开状态的最短时间(以秒为单位)。

max:指示在关闭连接之前可以在此连接上发送的最大请求数。

HTTP的优缺点

无状态

既然服务器**没有记忆能力**,它就无法支持需要连续多个步骤的事务操作。每次都得问一遍身份信息,不仅麻烦,而且还增加了不必要的数据传输量。由此出现了 Cookie 技术。

明文

HTTP 协议里还有一把优缺点一体的双刃剑,就是明文传输。明文意思就是协议里的报文(准确地说是 header 部分)不使用二进制数据,而是用简单可阅读的文本形式。

对比 TCP、UDP 这样的二进制协议,它的优点显而易见,不需要借助任何外部工具,用浏览器、Wireshark 或者 tcpdump 抓包后,直接用肉眼就可以很容易地查看或者修改,为我们的开发调试工作带来极大的便利。

当然缺点也是显而易见的,就是不安全,可以被监听和被窥探。因为无法判断通信双方的身份,不能判断报文是否被更改过。

性能

HTTP 的性能不算差,但不完全适应现在的互联网,还有很大的提升空间。

Cookie和Session的区别

  1. 数据存储位置:Cookie数据存储在客户端(通常是浏览器)中,而**Session数据存储在服务器端**。
  2. 数据安全性:由于**Cookie存储在客户端存在被窃取或篡改的风险。为了增加安全性可以使用加密、签名等手段来保护Cookie数据。而Session数据存储在服务器端,相对更安全,不容易被攻击者访问和修改。**
  3. 数据容量:Cookie大小有限制,一般为几KB到几十KB,不适合存储大量数据。而**Session数据一般存储在服务器端内存或数据库中,理论上可以存储更多的数据。**
  4. 性能开销:由于Cookie存储在客户端,每次请求都会将Cookie数据发送给服务器,增加了网络传输的开销。而**Session存储在服务器端,只需在客户端保存一个标识符(Session ID),减少了数据传输的开销。**
  5. 跨域支持:Cookie可以设置跨域访问,即一个域下的页面可以访问另一个域下的Cookie。而Session一般是针对单个域,不支持跨域访问。
  6. 生命周期:Cookie可以设置过期时间,可以是会话级别的(在浏览器关闭时失效)或持久性的(在指定时间后失效)。而Session可以根据服务器端的配置,设置过期时间或在一段时间不活动后自动销毁。

从使用角度来看,Cookie通常用于存储用户偏好设置、跟踪用户行为等。而Session通常用于存储用户登录状态、购物车信息等需要保密且数据量较大的情况。

需要注意的是,Cookie和Session并不是互斥的机制,它们经常配合使用。例如,服务器端会将Session ID 存储在Cookie中,使得客户端在后续请求中可以传递该Session ID,以便服务器识别和恢复对应的Session数据。

HTTPS

对称加密

简单的说,就是**用一个密钥,可以对一段信息进行加密,也可以使用其本身对这段信息进行解密,这就叫做对称加密。**

所以对称加密能防止中间人攻击吗?

很难。

首先,**如果能做到客户端和服务端都拥有这个密钥并且没有第三者知道,那理论上对称加密是可以的,**但是如何做到不可能让别人知道呢?

无论这个密钥是客户端生成发送给服务端,还是服务端生成发送给客户端,此时如果有中间人窃取了该密钥的信息,那往后传输的所谓“加密”数据,中间人也都可以将其解密并加密继续传输下去而不被人发现。

显然,本来我们就想要防范中间人攻击,而**对称加密想实施的前提就是保证没有中间人窃取密钥才可以**。这是不是有点像“问:我们如何将房价降下来呢?答:把房子的价格降下来,房价自然降下来”

非对称加密

简单说就是有两把密钥,一把叫做公钥、一把叫私钥,用公钥加密的内容必须用私钥才能解开,同样,私钥加密的内容只有公钥能解开。

所以非对称加密可以防范中间人攻击吗?

浏览器发送给服务器, 安全, 因为只有服务器才有私钥.

服务器发送给浏览器, 不安全, 因为公钥是公开的.

因为只有服务器有相应的私钥能解开公钥加密的数据

如果服务器用它的私钥加密数据传给浏览器,那么浏览器用公钥可以解密它,而这个公钥是一开始通过明文传输给浏览器的,若这个公钥被中间人劫持到了,那他也能用该公钥解密服务器传来的信息了。所以目前似乎只能保证由浏览器向服务器传输数据的安全性

使用两组就能保证服务器与浏览器的加密保密都成功.

这个方法并没有被大范围推广,并且也不可能被大范围推广。很重要的原因是非对称加密算法非常耗时,而对称加密快很多。

对称加密和非对称加密的综合版本

  1. 某网站拥有用于非对称加密的公钥A、私钥A’。
  2. 浏览器向网站服务器请求,服务器把公钥A明文给传输浏览器
  3. 浏览器随机生成一个用于对称加密的密钥X,用**公钥A加密后传给服务器**。
  4. 服务器拿到后用私钥A’解密得到密钥X
  5. 这样双方就都拥有密钥X了,且别人无法知道它。之后双方所有数据都通过密钥X加密解密即可。

成功!HTTPS基本就是采用了这种方案。

但是这并不是完美的,这仍然有漏洞喔!

对称加密和非对称加密的综合版本的漏洞

  1. 某网站有用于非对称加密的公钥A、私钥A’。
  2. 浏览器向网站服务器请求,服务器把公钥A明文给传输浏览器。
  3. 中间人劫持到公钥A,保存下来,把数据包中的公钥A替换成自己伪造的公钥B(它当然也拥有公钥B对应的私钥B’)。
  4. 浏览器生成一个用于对称加密的密钥X,用公钥B(浏览器以为是公钥A)加密后传给服务器。
  5. 中间人劫持后用私钥B’解密得到密钥X,再用公钥A加密后传给服务器。
  6. 服务器拿到后用私钥A’解密得到密钥X。

这样在双方都不会发现异常的情况下,中间人通过一套“狸猫换太子”的操作,掉包了服务器传来的公钥,进而得到了密钥X。**根本原因是浏览器无法确认收到的公钥是不是网站自己的,**因为公钥本身是明文传输的。

数字证书

网站在使用HTTPS前,需要向CA机构申领一份数字证书,数字证书里含有证书持有者信息、公钥信息等。**服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了,证书就如身份证,证明“该公钥对应该网站”。**而这里又有一个显而易见的问题,“证书本身的传输过程中,如何防止被篡改”?即如何证明证书本身的真实性?身份证运用了一些防伪技术,而数字证书怎么防伪呢?解决这个问题我们就真的接近胜利了!

如何防止数字证书被篡改?

简单理解就是**用签名者的私钥加密一串信息,将这串信息以及这串信息的加密版以及公钥都传给客户端,客户端收到信息后用公钥解密,****如果解密的结果和明文传过来的数据相符合,那自然可以证明该公钥是真的。**

每次发送HTTPS请求都需要在TLS/SSL层进行握手传输密钥吗?

服务器会为每个浏览器(或客户端软件)维护一个session ID,在**TLS握手阶段传给浏览器浏览器生成好密钥传给服务器后,服务器会把该密钥存到相应的session ID下,之后浏览器每次请求都会携带session ID,服务器会根据session ID找到相应的密钥并进行解密加密操作**,这样就不必要每次重新制作、传输密钥了!

TLS和SSL的区别

SSL(Secure Sockets Layer)和 TLS(Transport Layer Security)是用于加密通信的安全协议,它们的主要区别如下:

  1. 发展历史:
    • SSL:最早由 Netscape 公司开发,目前已经不再推荐使用。
    • TLS:TLS 是 SSL 的继任者,由 IETF(Internet Engineering Task Force)标准化,现在广泛应用。
  2. 名称差异:
    • SSL:SSL 有多个版本,如 SSL 2.0、SSL 3.0。
    • TLS:TLS 也有多个版本,如 TLS 1.0、TLS 1.1、TLS 1.2、TLS 1.3。TLS 1.3 是最新版本,更新了安全性和性能。
  3. 加密算法:
    • SSL:SSL 使用对称加密、非对称加密和哈希算法的组合进行数据加密和身份验证。
    • TLS:TLS 同样使用对称加密、非对称加密和哈希算法,但支持的算法更加丰富,并提供更高级的加密套件。
  4. 安全性:
    • SSL:SSL 存在一些安全漏洞和弱点,已被多次攻破,因此不再被推荐使用。
    • TLS:TLS 不断改进和修复先前版本的缺陷,提供更强大的安全性,被广泛接受并使用。
  5. 握手过程:
    • SSL:SSL 握手过程比较简单,包含了客户端和服务器之间的几个步骤,如协商加密算法、身份验证等。
    • TLS:TLS 握手过程更复杂,增加了一些新的步骤和交互,如支持更多的加密套件、完全前向保密和零知识证明等。

总结起来,SSL 是早期的安全协议,已经被弃用,推荐使用更安全和更强大的 TLS 协议。TLS 提供了更好的安全性、更丰富的加密算法选择、更完善的握手过程等特性,是当前广泛应用的加密通信标准。

Socket

什么是Scoket

网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。

但是,Socket所支持的协议种类也不光TCP/IP、UDP,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。

socket连接就是所谓的长连接,客户端和服务器需要互相连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉的,但是有时候网络波动还是有可能的

Socket偏向于底层。一般很少直接使用Socket来编程,框架底层使用Socket比较多

socket属于网络的那个层面

Socket是**应用层与TCP/IP协议族通信的中间软件抽象层**,它是一组接口。在设计模式中,Socket其实就是一个外观模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

Socket通讯的过程

  • 基于TCP:

    服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接

    在这时如果**有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。**

    客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

  • 基于UDP:UDP 协议是用户数据报协议的简称,也用于网络数据的传输。虽然 UDP 协议是一种不太可靠的协议,但有时在需要较快地接收数据并且可以忍受较小错误的情况下,UDP 就会表现出更大的优势。我客户端只需要发送,服务端能不能接收的到我不管

WebSocket协议

概念

  • WebSocket是**HTML5下一种新的协议websocket协议本质上是一个基于tcp的协议**)
  • 它**实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的**
  • Websocket是一个持久化的协议

原理

websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信
在websocket出现之前,web交互一般是基于http协议的短连接或者长连接 .
websocket是一种全新的协议,不属于http无状态协议,协议名为"ws" .

webSocket解决的问题

  1. http是一种**无状态协议每当一次会话完成后,服务端都不知道下一次的客户端是谁**,需要每次知道对方是谁,才进行相应的响应,因此本身对于实时通讯就是一种极大的障碍
  2. http协议采用一次请求,一次响应,每次请求和响应就携带有大量的header头,对于实时通讯来说,解析请求头也是需要一定的时间,因此,效率也更低下
  3. 最重要的是,需要客户端主动发,服务端被动发,也就是一次请求,一次响应,不能实现主动发送

websocket的改进

  1. 一旦WebSocket连接建立后,后续数据都以帧序列的形式传输
  2. 在客户端断开WebSocket连接或Server端中断连接前,不需要客户端和服务端重新发起连接请求
  3. 在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实现了“真·长链接”,实时性优势明显。

握手建立过程

在这里插入图片描述

握手阶段

websocket首次请求服务端建立连接,也是客户端发起的,基于http请求的。 请求头中多携带消息

GET /test HTTP/1.1          ##起始行 , 方法, URL , 协议
Host: server.example.com
Upgrade: websocket		   
Connection: Upgrade          ##连接状态 , 请求
Sec-WebSocket-Key: tFGdnEL/5fXMS9yKwBjllg==
Origin: http://example.com
Sec-WebSocket-Protocol: v10.stomp, v11.stomp, v12.stomp
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Version: 13

发送数据阶段

WebSocket使用二进制消息帧作为双向通信的媒介。何为消息帧?发送方将每个应用程序消息拆分为一个或多个帧,通过网络将它们传输到目的地,并重新组装解析出一个完整消息。

有别于HTTP/1.1文本消息格式(冗长的消息头和分隔符等),WebSocket消息帧规定一定的格式,以二进制传输,更加短小精悍。二者相同之处就是都是基于TCP/IP流式协议(没有规定消息边界)

在这里插入图片描述

  1. FIN: 1 bit表示该帧是否为消息的最后一帧。1-是,0-否。
  2. **RSV1,RSV2,RSV3: 1 bit each,预留(3位),扩展的预留标志。**一般情况为0,除非协商的扩展定义为非零值。如果接收到非零值且不为协商扩展定义,接收端必须使连接失败。
  3. Opcode: 4 bits,定义消息帧的操作类型,如果接收到一个未知Opcode,接收端必须使连接失败。(0x0-延续帧,0x1-文本帧,0x2-二进制帧,0x8-关闭帧,0x9-PING帧,0xA-PONG帧在接收到PING帧时,终端必须发送一个PONG帧响应,除非它已经接收到关闭帧),0x3-0x7保留给未来的非控制帧,0xB-F保留给未来的控制帧)
  4. **Mask: 1 bit,表示该帧是否为隐藏的,即被加密保护的。**1-是,0-否。Mask=1时,必须传一个Masking-key,用于解除隐藏(客户端发送消息给服务器端,Mask必须为1)。
  5. Payload length: 7 bits, 7+16 bits, or 7+64 bits,有效载荷数据的长度(扩展数据长度+应用数据长度,扩展数据长度可以为0)。
  6. Masking-key: 0 or 4 bytes,用于解除帧隐藏(加密)的key,Mask=1时不为空,Mask=0时不用传。
  7. Payload data: (x+y) bytes,有效载荷数据包括扩展数据(x bytes)和应用数据(y bytes)。有效载荷数据是用户真正要传输的数据。

关闭连接

挥手相对于握手要简单很多,客户端和服务器端任何一方都可以通过发送关闭帧来发起挥手请求。发送关闭帧的一方,之后不再发送任何数据给对方;接收到关闭帧的一方,如果之前没有发送过关闭帧,则必须发送一个关闭帧作为响应。关闭帧中可以携带关闭原因。

在发送和接收一个关闭帧消息之后,就认为WebSocket连接已关闭,且必须关闭底层TCP连接。

除了通过关闭握手来关闭连接外,WebSocket连接也可能在另一方离开或底层TCP连接关闭时突然关闭。

优点

较少的控制开销。在连接建立后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对于HTTP请求每次都要携带完整的头部,显著减少。
更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少。
保持连接状态。与HTTP不同的是,Websocket需要先建立连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等)。
更好的二进制支持。Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。
支持扩展。Websocket定义了扩展,用户可以扩展协议、实现部分自定义的子协议。
更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著提高压缩率。

Netty实现

public class WebsocketServer {
 
    private int port;
    public WebsocketServer(int port){
        this.port = port;
    }
    public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGoup = new NioEventLoopGroup(8);
        try{
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGoup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.DEBUG))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            // websocket协议是基于http之上的升级,因此加入HttpServerCodec
                            pipeline.addLast(new HttpServerCodec());
                            // 以块进行写操作,因此加入ChunkedWriteHandler
                            pipeline.addLast(new ChunkedWriteHandler());
                            // http数据在传输过程中会分段,因此加入 HttpObjectAggregator将多个段聚合
                            pipeline.addLast(new HttpObjectAggregator(4096));
                            // 加入websocket协议处理器,将 http 协议升级为 ws 协议 , 保持长连接
                            pipeline.addLast(new WebSocketServerProtocolHandler("/chat"));
                            // 加入业务处理器
                            pipeline.addLast(new MyTextWebSocketFrame());
                        }
                    });
            ChannelFuture channelFuture = serverBootstrap.bind(7777).sync();
            channelFuture.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workerGoup.shutdownGracefully();
        }
    }
 
    public static void main(String[] args) throws Exception {
        new WebsocketServer(7777).run();
    }
}
package eWebscoket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder;
import io.netty.handler.codec.http.websocketx.WebSocket08FrameEncoder;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

/**
 * netty对websocket协议实现测试:
 * 1.  netty 提供了{@link WebSocketServerProtocolHandler} handler用于处理websocket协议。
 * handler中有ws的握手支持,ping、pong响应,close请求这些支持, 同时将Text  与 binary 数据传递
 * 给之后的handler进行业务处理。WebSocketServerProtocolHandler 通过WebSocketServerProtocolHandshakeHandler 首次read请求
 * 确定websocket协议版本(一般是13), 给channel绑定了不容版本协议下的WebSocket13FrameDecoder。
 *
 * <p>
 * 2.WebSocketServerProtocolHandler在有新的channel连接注册回调方法中{@link WebSocketServerProtocolHandler#handlerAdded(ChannelHandlerContext)},
 * 会在当前handler中添加一个新的handler {@link WebSocketServerProtocolHandshakeHandler}专门用于处理首次客户端请求的握手操作, 查看
 * {@link io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandshakeHandler#channelRead(ChannelHandlerContext, Object)}的接收客户端数据的处理,会为客户返回
 * 一个FullHttpResponse,响应头中,含有确认更新为websocket协议的响应。 当这个channel写会给客户端,此时这个channel的通信协议就有http转为websocket,这个握手用的handler也会
 * 自己移除了。
 * <p>
 * 3. 握手处理过程:
 * 就会将pipLine中用于握手的http的解析handler给移除掉了,
 * p.remove(HttpContentCompressor.class);
 * p.remove(HttpObjectAggregator.class);
 * 然后在 HttpServerCodec 的 handler 之前添加 websocket协议的handler:
 * p.addBefore(ctx.name(), "wsdecoder", newWebsocketDecoder()); {@link WebSocket08FrameDecoder#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf, java.util.List)}
 * p.addBefore(ctx.name(), "wsencoder", newWebSocketEncoder()); {@link WebSocket08FrameEncoder#encode(io.netty.channel.ChannelHandlerContext, io.netty.handler.codec.http.websocketx.WebSocketFrame, java.util.List)}
 * 之后将response写会客户端成功后升级,将HttpServerCodec移除掉,删除代码在handshake()方法的写会回调中。
 * 在握手升级之后WebSocketServerProtocolHandshakeHandler 没有用了,就会将这个handler,替换成WebSocketServerProtocolHandler.forbiddenHttpRequestResponder()
 * 对非ws的请求拒绝处理。
 *
 * @author mahao
 * @date 2022/10/18
 */
public class ServerWebSocket {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        //添加http消息的转换,将socket数据流 转换为 HttpRequest, websocket协议添加这个是为了
                        //握手时候使用。 HttpServerCodec 与 HttpObjectAggregator会在第一次http请求后,被移除掉,握手结束了
                        //协议升级就会只用websocket协议了。
                        pipeline.addLast(new HttpServerCodec());
                        //未知
                        pipeline.addLast(new ChunkedWriteHandler());
                        //将拆分的http消息聚合成一个消息。
                        pipeline.addLast(new HttpObjectAggregator(8096));

                        //用户websocket协议的 握手,ping pang处理, close处理,对于二进制或者文件数据,直接交付给下层
                        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

                        pipeline.addLast("myHandler", new WebSocketHandler());

                    }
                });
        ChannelFuture channelFuture = serverBootstrap.bind(9999).sync();
        channelFuture.channel().closeFuture().sync();

        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();

    }
}

new ChunkedWriteHandler());
//将拆分的http消息聚合成一个消息。
pipeline.addLast(new HttpObjectAggregator(8096));

                    //用户websocket协议的 握手,ping pang处理, close处理,对于二进制或者文件数据,直接交付给下层
                    pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

                    pipeline.addLast("myHandler", new WebSocketHandler());

                }
            });
    ChannelFuture channelFuture = serverBootstrap.bind(9999).sync();
    channelFuture.channel().closeFuture().sync();

    bossGroup.shutdownGracefully();
    workerGroup.shutdownGracefully();

}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木 木 水.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值