# 网络

七层模型和相关协议

OSI7
应用层:允许访问 OSI 环境的手段(应用协议数据单元 APDU)
表示层:对数据进行翻译、加密和压缩(表示协议数据单元 PPDU)
会话层:建立、管理和终止会话(会话协议数据单元 SPDU)
传输层:提供端到端的可靠报文传递和错误恢复(段 Segment)
网络层:负责数据包从源到宿的传递和网际互连(包 PackeT)
数据链路层:将比特组装成帧和点到点的传递(帧 Frame)
物理层:通过媒介传输比特,确定机械及电气规范(比特 Bit)

ICMP 协议: 因特网控制报文协议。它是 TCP/IP 协议族的一个子协议,用于在 IP 主机、路由器之间传递控制消息。
TFTP 协议: 是 TCP/IP 协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。
HTTP 协议: 超文本传输协议,是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。
DHCP 协议: 动态主机配置协议,是一种让系统得以连接到网络上,并获取所需要的配置参数手段。

TCP/IP五层协议

TCP/IP5

应用层 (application layer):直接为应用进程提供服务。应用层协议定义的是应用进程间通讯和交互的规则,不同的应用有着不同的应用层协议,如 HTTP 协议(万维网服务)、FTP 协议(文件传输)、SMTP 协议(电子邮件)、DNS(域名查询)等。
传输层 (transport layer):有时也译为运输层,它负责为两台主机中的进程提供通信服务。该层主要有以下两种协议:
1、传输控制协议 (Transmission Control Protocol,TCP):提供面向连接的、可靠的数据传输服务,数据传输的基本单位是报文段(segment);
2、用户数据报协议 (User Datagram Protocol,UDP):提供无连接的、尽最大努力的数据传输服务,但不保证数据传输的可靠性,数据传输的基本单位是用户数据报。
网络层 (internet layer):有时也译为网际层,它负责为两台主机提供通信服务,并通过选择合适的路由将数据传递到目标主机。
数据链路层 (data link layer):负责将网络层交下来的 IP 数据报封装成帧,并在链路的两个相邻节点间传送帧,每一帧都包含数据和必要的控制信息(如同步信息、地址信息、差错控制等)。
物理层 (physical Layer):确保数据可以在各种物理媒介上进行传输,为数据的传输提供可靠的环境。

TCP

IP

URL组成
属性含义示例
protocal协议http:
hostname主机名127.0.0.1
port端口号8001
host主机127.0.0.1:8001
catalog目录/xxx/xxx/
pathname访问页面index.html
hash哈希值(锚)#/aaa/bbb
search搜索内容?a=100&b=20

# HTTP

HTTP协议的优点和缺点

HTTP 是超文本传输协议,它定义了客户端和服务器之间交换报文的格式和方式,默认使用 80 端口。它使用 TCP 作为传输层协议,保证了数据传输的可靠性。

HTTP 协议具有以下优点:

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

HTTP 协议具有以下缺点:

  1. 无状态:HTTP 是一个无状态的协议,HTTP 服务器不会保存关于客户的任何信息。
  2. 明文传输:协议中的报文使用的是文本形式,这就直接暴露给外界,不安全。
  3. 不安全
    (1)通信使用明文(不加密),内容可能会被窃听;
    (2)不验证通信方的身份,因此有可能遭遇伪装;
    (3)无法证明报文的完整性,所以有可能已遭篡改;
HTTP请求报文组成
  1. 请求⾏:请求⽅法字段、URL 字段、HTTP 协议版本字段。它们⽤空格分隔。例如,GET /index.html HTTP/1.1。
  2. 请求头部:请求头部由关键字 / 值对组成,每⾏⼀对,关键字和值⽤英⽂冒号 “:” 分隔
  3. 空行:回车符 + 换行符
  4. 请求体: post put 等请求携带的数据

请求报文

请求报文

HTTP响应报文组成

响应报文由四部分组成(响应行 + 响应头 + 空行 + 响应体)

响应行:HTTP 版本 + 空格 + 状态码 + 空格 + 状态码描述 + 回车符(CR) + 换行符(LF)
响应头:字段名 + 冒号 + 值 + 回车符 + 换行符
空行:回车符 + 换行符
响应体:由用户自定义添加,如 post 的 body 等

响应报文

请求头字段、响应头字段有哪些,作用属性?

参考 MDN
(https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers)

HTTP状态码

(1)2XX 成功

  • 200 OK,表示从客户端发来的请求在服务器端被正确处理
  • 204 No content,表示请求成功,但响应报文不含实体的主体部分
  • 205 Reset Content,表示请求成功,但响应报文不含实体的主体部分,但是与 204 响应不同在于要求请求方重置内容
  • 206 Partial Content,请求指定范围部分资源

(2)3XX 重定向

  • 301 moved permanently,永久性重定向,表示资源已被分配了新的 URL
  • 302 found,临时性重定向,表示资源临时被分配了新的 URL
  • 303 see other,表示资源存在着另一个 URL,应使用 GET 方法获取资源
  • 304 not modified,表示服务器允许访问资源,但因发生请求未满足条件的情况(协商缓存)
  • 307 temporary redirect,临时重定向,和 302 含义类似,但是期望客户端保持请求方法不变向新的地址发出请求(307 会遵守浏览器标准,不会从 POST 变成 GET。但是对于处理请求的行为时,不同浏览器还是会出现不同的情况。规范要求浏览器继续向 Location 的地址 POST 内容。规范要求浏览器继续向 Location 的地址 POST 内容。)

(3)4XX 客户端错误

  • 400 bad request,请求报文存在语法错误
  • 401 unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息
  • 403 forbidden,表示对请求资源的访问被服务器拒绝
  • 404 not found,表示在服务器上没有找到请求的资源
  • 405 method not allowed 服务器禁止使用该请求方法(客户端可以通过 OPTIONS 方法(预检)来查看服务器允许的访问方法)

(4)5XX 服务器错误

  • 500 internal sever error,表示服务器端在执行请求时发生了错误
  • 501 Not Implemented,表示服务器不支持当前请求所需要的某个功能
  • 502 Bad Gatway 网关或代理服务器错误
  • 503 service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求
  • 504 Gateway Timeout 网关或代理服务器超时
常见的HTTP请求方法
  • GET: 向服务器获取数据
  • POST:将实体提交到指定的资源,通常会造成服务器资源的修改
  • PUT:上传文件,更新数据
  • DELETE:删除服务器上的对象
  • HEAD:获取报文首部,与 GET 相比,不返回报文主体部分
  • OPTIONS:询问支持的请求方法,用来跨域请求
  • CONNECT:要求在与代理服务器通信时建立隧道,使用隧道进行 TCP 通信
  • TRACE: 回显服务器收到的请求,主要⽤于测试或诊断
get和post请求的区别
  • 应用场景:GET 请求是一个幂等安全的请求,一般 Get 请求用于对服务器资源不会产生影响的场景,比如说请求一个网页的资源。而 Post 是一个不幂等不安全的请求,一般用于对服务器资源会产生影响的情景,比如注册用户这一类的操作。
  • 是否缓存:因为两者应用场景不同,浏览器一般会对 Get 请求缓存,但很少对 Post 请求缓存。
  • 发送的报文格式:Get 请求的报文中实体部分为空,Post 请求的报文中实体部分一般为向服务器发送的数据。
  • 安全性:Get 请求可以将请求的参数放入 url 中向服务器发送,这样的做法相对于 Post 请求来说是不太安全的,因为请求的 url 会被保留在历史记录中。
  • 请求长度:浏览器由于对 url 长度的限制,所以会影响 get 请求发送数据时的长度。这个限制是浏览器规定的,并不是 RFC 规定的。
  • 参数类型:post 的参数传递支持更多的数据类型。
OPTIONS请求方法及使用场景

OPTIONS 方法是用于请求获得由 Request-URI 标识的资源在请求 / 响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。该请求方法的响应不能缓存。

OPTIONS 请求方法的主要用途有两个:

  • 获取服务器支持的所有 HTTP 请求方法;
  • 用来检查访问权限。例如:在进行 CORS 跨域资源共享时,对于复杂请求,就是使用 OPTIONS 方法发送嗅探请求,以判断是否有对指定资源的访问权限。
谈谈网络性能优化
  1. 避免请求:采用强缓存和协商缓存,DNS 缓存,CDN 负载均衡
  2. 减少请求:1. 资源的懒加载 2. 合并请求,如将静态资源合并成一个大文件 3. 代理重定向
  3. 压缩:1. 图片视频等资源进行有损压缩 2. 代码文本类进行无损压缩(Gzip)

# HTTP 各个版本

简述HTTP各个版本改进

HTTP2.0

  1. 二进制格式:HTTP2.0 基本单位为二进制,以往是采用文本形式,健壮性不是很好,现在采用二进制格式,更方便更健壮
  2. 多路复用:把多个请求当做多个流,请求响应数据分成多个帧(帧可以标记资源让服务端识别),不同流中的帧交错发送,解决了 TCP 连接数量多、慢和队头阻塞的问题,所以对于同一个域名只用创建一个连接就可以了
  3. 压缩消息头:客户端和服务端共同维护一个字典,重复发送同样请求头时只需要发送索引即可
  4. HTTP2.0 服务端推送,浏览器发送请求后,服务端会主动发送与这个请求相关的资源,之后浏览器就不用再次发送后续的请求了

HTTP1.1

  1. 长连接,可以在一个 TCP 连接上发送多个请求和响应,减少多次握手挥手消耗,但存在队头阻塞问题
  2. 缓存处理新增 E-Tag、If-None-Match 之类的缓存来来控制缓存
  3. 资源请求方面,在 http1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,http1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
  4. http1.1 中新增了 host 字段,用来指定服务器的域名。http1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个 IP 地址。因此有了 host 字段,这样就可以将请求发往到同一台服务器上的不同网站。
  5. 多了 PUT、HEAD、OPTIONS 等请求方法
谈谈HTTP2中的多路复用,为什么1.1中不能使用

在 HTTP1.1 中即使开启了 Keep-Alive,解决了多次连接的问题,但是依然有两个效率上的问题:
一是服务端必须顺序响应文件,容易造成队头阻塞,二是连接数过多导致的性能问题。
HTTP2 的多路复用就是为了解决上述的两个性能问题。
在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。
多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。
HTTP/1.1 不是二进制传输,而是通过文本进行传输。由于没有流的概念,在使用并行传输(多路复用)传递数据时,接收端在接收到响应后,并不能区分多个响应分别对应的请求,所以无法将多个响应的结果重新进行组装,也就实现不了多路复用。

页面有多张图片,HTTP是怎样的加载表现?
  • 在 HTTP 1 下,浏览器对一个域名下最大 TCP 连接数为 6,所以会请求多次。可以用多域名部署解决。这样可以提高同时请求的数目,加快页面图片的获取速度。
  • 在 HTTP 2 下,可以一瞬间加载出来很多资源,因为,HTTP2 支持多路复用,可以在一个 TCP 连接中发送多个 HTTP 请求。
讲讲头部压缩算法

HTTP2 的头部压缩是 HPACK 算法。在客户端和服务器两端建立 “字典”,用索引号表示重复的字符串,采用哈夫曼编码来压缩整数和字符串,可以达到 50%~90% 的高压缩率。

具体来说:

  • 在客户端和服务器端使用 “首部表” 来跟踪和存储之前发送的键值对,对于相同的数据,不再通过每次请求和响应发送;
  • 首部表在 HTTP/2 的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
  • 每个新的首部键值对要么被追加到当前表的末尾,要么替换表中之前的值。

头部压缩

讲讲HTTP3.0

HTTP/3 基于 UDP 协议实现了类似于 TCP 的多路复用数据流、传输可靠性等功能,这套功能被称为 QUIC 协议。

http3.0

  1. 流量控制、传输可靠性功能:QUIC 在 UDP 的基础上增加了一层来保证数据传输可靠性,它提供了数据包重传、拥塞控制、以及其他一些 TCP 中的特性。
  2. 集成 TLS 加密功能:目前 QUIC 使用 TLS1.3,减少了握手所花费的 RTT 数。
  3. 多路复用:同一物理连接上可以有多个独立的逻辑数据流,实现了数据流的单独传输,解决了 TCP 的队头阻塞问题。
  4. 快速握手:由于基于 UDP,可以实现使用 0 ~ 1 个 RTT 来建立连接。

3.0

# HTTPS

HTTPS握手过程

参考小林 coding 中的解析

讲讲TLS/SSL的工作原理(HTTPS如何保证安全)

TLS/SSL 全称安全传输层协议(Transport Layer Security), 是介于 TCP 和 HTTP 之间的一层安全协议,不影响原有的 TCP 协议和 HTTP 协议,所以使用 HTTPS 基本上不需要对 HTTP 页面进行太多的改造。

TLS/SSL 的功能实现主要依赖三类基本算法:散列函数 hash、对称加密、非对称加密。这三类算法的作用如下:

  1. 基于散列函数验证信息的完整性
  2. 对称加密算法采用协商的秘钥对数据加密
  3. 非对称加密实现身份认证和秘钥协商

TLS

(1)散列函数 hash
常见的散列函数有 MD5、SHA1、SHA256。该函数的特点是单向不可逆,对输入数据非常敏感,输出的长度固定,任何数据的修改都会改变散列函数的结果,可以用于防止信息篡改并验证数据的完整性。

特点:在信息传输过程中,散列函数不能三都实现信息防篡改,由于传输是明文传输,中间人可以修改信息后重新计算信息的摘要,所以需要对传输的信息和信息摘要进行加密。
(2)对称加密
对称加密的方法是,双方使用同一个秘钥对数据进行加密和解密。但是对称加密的存在一个问题,就是如何保证秘钥传输的安全性,因为秘钥还是会通过网络传输的,一旦秘钥被其他人获取到,那么整个加密过程就毫无作用了。 这就要用到非对称加密的方法。

常见的对称加密算法有 AES-CBC、DES、3DES、AES-GCM 等。相同的秘钥可以用于信息的加密和解密。掌握秘钥才能获取信息,防止信息窃听,其通讯方式是一对一。

特点:对称加密的优势就是信息传输使用一对一,需要共享相同的密码,密码的安全是保证信息安全的基础,服务器和 N 个客户端通信,需要维持 N 个密码记录且不能修改密码。
(3)非对称加密
非对称加密的方法是,我们拥有两个秘钥,一个是公钥,一个是私钥。公钥是公开的,私钥是保密的。用私钥加密的数据,只有对应的公钥才能解密,用公钥加密的数据,只有对应的私钥才能解密。我们可以将公钥公布出去,任何想和我们通信的客户, 都可以使用我们提供的公钥对数据进行加密,这样我们就可以使用私钥进行解密,这样就能保证数据的安全了。但是非对称加密有一个缺点就是加密的过程很慢,因此如果每次通信都使用非对称加密的方式的话,反而会造成等待时间过长的问题。

常见的非对称加密算法有 RSA、ECC、DH 等。秘钥成对出现,一般称为公钥(公开)和私钥(保密)。公钥加密的信息只有私钥可以解开,私钥加密的信息只能公钥解开,因此掌握公钥的不同客户端之间不能相互解密信息,只能和服务器进行加密通信,服务器可以实现一对多的的通信,客户端也可以用来验证掌握私钥的服务器的身份。

特点:非对称加密的特点就是信息一对多,服务器只需要维持一个私钥就可以和多个客户端进行通信,但服务器发出的信息能够被所有的客户端解密,且该算法的计算复杂,加密的速度慢。

综合上述算法特点,TLS/SSL 的工作方式就是客户端使用非对称加密与服务器进行通信,实现身份的验证并协商对称加密使用的秘钥。对称加密算法采用协商秘钥对信息以及信息摘要进行加密通信,不同节点之间采用的对称秘钥不同,从而保证信息只能通信双方获取。这样就解决了两个方法各自存在的问题。

SSL连接断开后如何恢复

Session id:通过将会话时产生的编号再一次传给服务器,若服务器有该记录则可以继续使用
Session Ticket:session ticket 是服务器在上一次对话中发送给客户的,这个 ticket 是加密的,只有服务器可能够解密,里面包含了本次会话的信息,比如对话密钥和加密方法等。这样不管我们的请求是否转移到其他的服务器上,当服务器将 ticket 解密以后,就能够获取上次对话的信息,就不用重新生成对话秘钥了。

http 和 https 的区别及优缺点?
  1. http 是超文本传输协议,信息是明文传输,HTTPS 协议要比 http 协议安全,https 是具有安全性的 ssl 加密传输协议,可防止数据在传输过程中被窃取、改变,确保数据的完整性 (当然这种安全性并非绝对的,对于更深入的 Web 安全问题,此处暂且不表)。
  2. http 协议的默认端口为 80,https 的默认端口为 443。
  3. http 的连接很简单,是无状态的。https 握手阶段比较费时,会使页面加载时间延长 50%,增加 10%~20% 的耗电。
  4. https 缓存不如 http 高效,会增加数据开销。
  5. Https 协议需要 ca 证书,费用较高,功能越强大的证书费用越高。
  6. SSL 证书需要绑定 IP,不能再同一个 IP 上绑定多个域名,IPV4 资源支持不了这种消耗。

# DNS

DNS同时使用TCP和UDP协议?
  1. 在区域传输的时候使用 TCP 协议
    辅域名服务器会定时(一般 3 小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,会执行一次区域传送,进行数据同步。区域传送使用 TCP 而不是 UDP,因为数据同步传送的数据量比一个请求应答的数据量要多得多。
    TCP 是一种可靠连接,保证了数据的准确性。
  2. 在域名解析的时候使用 UDP 协议
    客户端向 DNS 服务器查询域名,一般返回的内容都不超过 512 字节,用 UDP 传输即可。不用经过三次握手,这样 DNS 服务器负载更低,响应更快。理论上说,客户端也可以指定向 DNS 服务器查询时用 TCP,但事实上,很多 DNS 服务器进行配置的时候,仅支持 UDP 查询包。

# TCP/UDP/WebSocket

TCP三次握手四次挥手

握手:

  1. 发送端发送 SYN 标志(我要发送请求)
  2. 接收端回复一个 SYN/ACK(ok 收到,你发吧)
  3. 发送端再回复 ACK 握手结束(ok)

挥手

  1. 主动关闭方发送 FIN(我要关闭请求了)【注意这里如果还有未完毕的请求(未收到对方 ACK)会继续发送或接收】
  2. 被关闭方回复 ACK(知道了,等我这边处理请求完先)
  3. 被关闭方发送 FIN(处理完了,我也要关闭请求了)
  4. 主动关闭方回复 ACK(知道了)

如果省略第三次握手,则遇到网络差的情况会阻塞导致再建立一条新的 TCP 握手请求,等到网络畅通时旧的网络请求会再工作导致 bug

TCP和UDP的区别

TCP 是面向有连接的协议,一对一、可靠、面向字节流、提供拥塞控制、提供全双工通信
UDP 是面向无连接的协议,一对多、不可靠、面向报文

TCP/IP / 如何保证数据包传输的有序可靠?

对字节流分段并进行编号然后通过 ACK 回复和超时重发这两个机制来保证。

  1. 为了保证数据包的可靠传递,发送方必须把已发送的数据包保留在缓冲区;
  2. 并为每个已发送的数据包启动一个超时定时器;
  3. 如在定时器超时之前收到了对方发来的应答信息(可能是对本包的应答,也可以是对本包后续包的应答),则释放该数据包占用的缓冲区;
  4. 否则,重传该数据包,直到收到应答或重传次数超过规定的最大次数为止。
  5. 接收方收到数据包后,先进行 CRC 校验,如果正确则把数据交给上层协议,然后给发送方发送一个累计应答包,表明该数据已收到,如果接收方正好也有数据要发给发送方,应答包也可方在数据包中捎带过去。
TCP的拥塞控制机制

TCP 的拥塞控制机制主要是以下四种机制:

  • 慢启动(慢开始)
  • 拥塞避免
  • 快速重传
  • 快速恢复
  1. 慢启动(慢开始)
    ● 在开始发送的时候设置 cwnd = 1(cwnd 指的是拥塞窗口)
    ● 思路:开始的时候不要发送大量数据,而是先测试一下网络的拥塞程度,由小到大增加拥塞窗口的大小。
    ● 为了防止 cwnd 增长过大引起网络拥塞,设置一个慢开始门限 (ssthresh 状态变量)
    ○ 当 cnwd < ssthresh,使用慢开始算法
    ○ 当 cnwd = ssthresh,既可使用慢开始算法,也可以使用拥塞避免算法
    ○ 当 cnwd > ssthresh,使用拥塞避免算法
  2. 拥塞避免
    ● 拥塞避免未必能够完全避免拥塞,是说在拥塞避免阶段将拥塞窗口控制为按线性增长,使网络不容易出现阻塞。
    ● 思路: 让拥塞窗口 cwnd 缓慢的增大,即每经过一个返回时间 RTT 就把发送方的拥塞控制窗口加一
    ● 无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞,就把慢开始门限设置为出现拥塞时的发送窗口大小的一半。然后把拥塞窗口设置为 1,执行慢开始算法。如图所示:
    a
    其中,判断网络出现拥塞的根据就是没有收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为无法判定,所以都当做拥塞来处理。
  3. 快速重传
    ● 快重传要求接收方在收到一个失序的报文段后就立即发出重复确认 (为的是使发送方及早知道有报文段没有到达对方)。发送方只要连续收到三个重复确认就立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。
    ● 由于不需要等待设置的重传计时器到期,能尽早重传未被确认的报文段,能提高整个网络的吞吐量
  4. 快速恢复
    ● 当发送方连续收到三个重复确认时,就执行 “乘法减小” 算法,把 ssthresh 门限减半。但是接下去并不执行慢开始算法。
    ● 考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将 cwnd 设置为 ssthresh 的大小,然后执行拥塞避免算法。
    1
TCP的流量控制机制

一般来说,流量控制就是为了让发送方发送数据的速度不要太快,要让接收方来得及接收。TCP 采用大小可变的滑动窗口进行流量控制,窗口大小的单位是字节。这里说的窗口大小其实就是每次传输的数据大小。

  • 当一个连接建立时,连接的每一端分配一个缓冲区来保存输入的数据,并将缓冲区的大小发送给另一端。
  • 当数据到达时,接收方发送确认,其中包含了自己剩余的缓冲区大小。(剩余的缓冲区空间的大小被称为窗口,指出窗口大小的通知称为窗口通告 。接收方在发送的每一确认中都含有一个窗口通告。)
  • 如果接收方应用程序读数据的速度能够与数据到达的速度一样快,接收方将在每一确认中发送一个正的窗口通告。
  • 如果发送方操作的速度快于接收方,接收到的数据最终将充满接收方的缓冲区,导致接收方通告一个零窗口 。发送方收到一个零窗口通告时,必须停止发送,直到接收方重新通告一个正的窗口。
什么是粘包问题,如何解决?

默认情况下,TCP 连接会启⽤延迟传送算法 (Nagle 算法), 在数据发送之前缓存他们。如果短时间有多个数据发送,会缓冲到⼀起作⼀次发送 (缓冲⼤⼩⻅ socket.bufferSize ), 这样可以减少 IO 消耗提⾼性能.
粘包情况有两种,一种是粘在一起的包都是完整的数据包,另一种情况是粘在一起的包有不完整的包。

为了避免粘包现象,可采取以下几种措施:

  1. 进⾏封包 / 拆包:封包 / 拆包是⽬前业内常⻅的解决⽅案了。即给每个数据包在发送之前,于其前 / 后放⼀些有特征的数据,然后收到数据的时 候根据特征数据分割出来各个数据包。
  2. 关闭 Nagle 算法,在 Node.js 中你可以通过 socket.setNoDelay () ⽅法来关闭 Nagle 算法,让每⼀次 send 都不缓冲直接发送
  3. 多次发送之前间隔⼀个等待时间

以上提到的三种措施,都有其不足之处。

不足

  1. 第二种该⽅法⽐较适⽤于每次发送的数据都⽐较⼤ (但不是⽂件那么⼤), 并且频率不是特别⾼的场景。如果是每次发送的数据量⽐较⼩,并且频率特别⾼的,关闭 Nagle 纯属⾃废武功。另外,该⽅法不适⽤于⽹络较差的情况,因为 Nagle 算法是在服务端进⾏的包合并情况,但是如果短时间内客户端的⽹络情况不好,或者应⽤层由于某些原因不能及时将 TCP 的数据 recv, 就会造成多个包在客户端缓冲从⽽粘包的情况。 (如果是在稳定的机房内部通信那么这个概率是⽐较⼩可以选择忽略的)
  2. 第三种对于⽐较频繁的场景⽽⾔传输效率实在太低,不过⼏乎不⽤做什么处理.

一种比较周全的对策是:接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开。实验证明这种方法是高效可行的。

黏包只在在流传输中出现,UDP 不会出现粘包,因为它有消息边界:在每个 UDP 包中就有了消息头(消息来源地址,端⼝等信息),这样对于接收端来说就容易进⾏区分处理了。传输协议把数据当作⼀条独⽴的消息在⽹上传输,接收端只能接收独⽴的消息。接收端⼀次只能接收发送端发出的⼀个数据包,如果⼀次接受数据的⼤⼩⼩于发送端⼀次发送的数据⼤⼩,就会丢失⼀部分数据,即使丢失,接受端也不会分两次去接收。
如果是传输⽂件的话,那么根本不⽤处理粘包的问题,来⼀个包拼⼀个包就好了。但是如果是多条消息,或者是别的⽤途的数据那么就需要处理粘包.

A、B 机器正常连接后,B 机器突然重启,问 A 此时处于 TCP 什么状态?

因为 B 会在重启之后进入 tcp 状态机的 listen 状态,只要当 a 重新发送一个数据包(无论是 syn 包或者是应用数据),b 端应该会主动发送一个带 rst 位的重置包来进行连接重置,所以 a 应该在 syn_sent 状态

阅读次数

请我喝[茶]~( ̄▽ ̄)~*

EvilMoOd 微信支付

微信支付

EvilMoOd 支付宝

支付宝