计算机网络


1 简述静态路由和动态路由
1)静态路由是由系统管理员设计与构建的路由表规定的路由。
使用场景:适用于网关数量有限,且网络拓朴结构不经常变化的网络。
缺点:不能动态地适用网络状况的变化,当网络状况变化后必须由网络管理员修改路由表。
2)动态路由是由路由选择协议而动态构建的,路由协议之间通过交换各自所拥有的路由信息实时更新路由表的内容。
使用场景:用于需要自动学习网络的拓朴结构,并更新路由表的场景。
缺点:路由广播更新信息将占据大量的网络带宽。
2)路由协议有哪些,如何更新
2-1)RIP 路由协议:RIP 采用距离向量算法,即路由器根据距离选择路由,所以也称为距离向量协议。路由器收集所有可到达目的地的不同路径,并且保存有关到达每个目的地的最少站点数的路 径信息。RIP 使用非常广泛,它简单、可靠,便于配置。但是 RIP 只适用于小型的同构网络,因 为它允许的最大站点数为 15。
优点:简单、可靠,便于配置;
适用场景:允许的最大站点数为 15,只适用于小型的同构网络。
2-2)OSPF 路由协议:0SPF 是一种基于链路状态的路由协议,需要每个路由器向其同一管理域的所有其它路 由器发送链路状态广播信息。与 RIP 不同,OSPF 将一个自治域再划分为区,相应地即有两种类型的路由选择方式: 当源和目的地在同一区时,采用区内路由选择;当源和目的地在不同区时,则采用区间路由 选择。这就大大减少了网络开销,并增加了网络的稳定性。

详述客户端与服务器 3 次握手过程
1)第 1 次握手
- 客户端向服务器发送一个 SYNC 包(同步包),并设置同步标志位
SYN = 1(此报文用来建立连接,表示此报文需要对方发送同步标志位SYN与确认标志位ACK的报文),并且生成一个序列号seq=x。发送后,客户端进入同步发送状态(SYN_SENT),等待服务器的确认;
2)第 2 次握手
- 服务器收到客户端的同步包
SYN包后,发送一个确认包(同步标志位SYN+ 确认标志位ACK)报文作为响应,并且 确认号ack=x+1(表示服务器接收到了客户端的同步SYN包),同时随机生成一个随机序列号seq=y。发送后,服务端进入同步接收状态(SYN_RECV),等待客户端的确认;
3)第 3 次握手
- 客户端收到服务端的确认包后,也会发送确认包给服务端,序列号
seq=y+1(表示客户端接收到了服务端的确认包)。此包发送后,客户端与服务端均进入连接建立ESTABLISHED状态。
如果 3 次握手中有 1 次失败,情况会如何?
1)若第一次或第二次握手信息丢失(即同步包丢失),请求方都不会得到确认包,超时后重传;
2)如果第三次握手消息丢失(即确认包丢失),服务端处于同步接收状态 SYN_RECV,会根据 TCP 的超时重传机制,重传请求包。
补充:如果在客户端发送完确认包后,服务端突然挂断。客户端以为建立了连接,发送 TCP 请求报文。客户端会因为没有收到服务端的响应报文而超时重传确认包。
谈谈为什么是 3 次握手,为什么不可以是 更少的 一二次,或更多的四五次?
1)若是一次握手,客户端的请求报文未到达服务端,客户端理所当然认为建立了连接,不断发送无人接收的数据包给服务端,造成网络拥挤。在超过一次的握手协议中,如果客户端未收到应答报文,会进行重传。
2)若是二次握手,服务端的应答报文未到达客户端,服务端理所当然认为建立了连接,为该连接创建了套接字,白白浪费系统资源。在超过二次的握手协议里,若服务端未收到自己应答报文的应答报文,会重传。
3)第三次握手报文就是响应服务端的响应。若该报文未到达服务端,一段时间后服务端会重传第二次报文。
4)三次握手已经能确保可靠性传输了,故无需使用第四五次的握手。
详细阐述 TCP 4 次挥手
由于 TCP 是全双工,在关闭连接时,每个方向都需要单独关闭,所以断开连接过程需要 4 次挥手。
1)第一次挥手:客户端发送一个结束报文(结束标志FIN=1,序列号seq=u),表示客户端无要发送的数据,希望关闭连接。客户端进入结束等待第一阶段状态(FIN_WAIT_1);
2)第二次挥手:服务端收到结束报文后,会发送确认报文(ACL=1, ack=u+1)给客户端,表示服务端收到对方断开连接的请求,但服务端仍可能有数据需要发送;
3)第三次挥手:当服务器发送完所有数据后,它会发送一个结束报文(FIN=1, seq=w),表示服务端无数据要发送给客户端,希望关闭连接;
4)第四次挥手:客户端收到服务器的结束报文后,会发送一个确认报文(ACK=1, ack=w+1),并进入等待状态 TIME_WAIT,等待时长为两倍的最大报文段寿命(2MSL),以确保服务端收到了客户端的确认报文。

谈谈本机如何干预域名解析
通过在 /etc/hosts 文件修改本机 host 来干预域名解析。
谈谈 DNS 劫持
DNS 劫持就是劫持了 DNS 服务器,通过某些手段取得某域名的解析记录控制权。进而修改域名的解析结果。其结果是对特定的网址不能访问或访问的是假网址,从而实现窃取资料等目的。
简述网关的作用,同一网段的主机如何通信
- 网关的用途主要包括网络协议转换和路由功能。
- 若发送主机的 ARP 表中无目的主机对应的表项,则发送主机广播以目的主机 IP 为内容的请求,目的主机接收到此 ARP 请求后,会将自己的 MAC 地址和 IP 地址封装后发送给对方主机。发送主机接收后,在自身的 ARP 表中建立目的主机的对应表项,之后即可向目的主机发送数据。
简述 CSRF 跨站请求伪造思想及解决办法
1)CSRF 攻击是一种请求伪造的攻击方式,它利用的是服务器不能识别用户的类型从而盗取用户的信息来攻击;
2)解决方法:(从服务器端着手,增强服务器的识别能力)token 验证。当用户正常访问服务器时,服务器会生成随机字符串 token 保存在 session,并将其以隐藏的方式返回给客户端。客户端每次请求都带着这个 token,服务器根据该 token 判断该请求是否合法。
简述 TCP 和 UDP 区别,它们的头部结构是什么?
TCP 头部有哪些字段: https://zhuanlan.zhihu.com/p/431583008
源端口,目的端口,请求标志位Seq,响应标志位Ack,终止标志位Fin,检验和,滑动窗口大小
1)TCP 是有连接的,有连接是指在双方进行通信前,必须通过三次握手建立连接;
UDP 是无连接的。
2)TCP协议保证数据按序发送,按序到达,提供超时重传来保证可靠性;
UDP 不保证按序到达,它只是努力交付。
3)TCP协议所需资源多,TCP首部需20个字段;
UDP 首部字段只需 8 个字段
4)TCP有流量控制和拥塞控制;UDP没有,网络拥堵不会影响发送端的发送速率
5)TCP是一对一的连接,而UDP则可以支持一对一,多对多,一对多的通信;
[UDP的多播是基于分组的,在这个分组的所有主机都接收我的数据报文]
TCP面向的是字节流的服务,UDP面向的是报文的服务。
1、TCP 重传机制、滑动窗口、流量控制、拥塞控制
TCP 通过重传机制、滑动窗口、流量控制、拥塞控制等 4 大机制保证连接的可靠性。
1.1 重传机制
在数据包丢失/确认应答丢失的情况下,TCP 会触发超时重传机制。
RTT(Round-Trip Time,往返时延)即数据发送时刻到确认时刻的差值。超时重传的时间应该略大于 RTT 的值。
1.2 滑动窗口
滑动窗口的概念是,滑动窗口内的数据包无需等待确认应答即可连续发送。滑动窗口本质是发送方和接收方发送数据和接收数据的缓冲区。好处:
- 1)提供 TCP 可靠性:通过窗口内报文的确认应答机制提供 TCP 的可靠性;
- 2)提供 TCP 流控特性:通过动态调整发送端的窗口大小,以适应网络拥塞和接收端的接收能力。
- 3)减少通信时长:减少等待确认应答而导致的通信时长。
1.3 流量控制
流量控制解决的是收发双方流量的问题。若不进行流量控制,在接收方缓冲区满的时候,发送方持续发送数据,会造成丢包,继而造成丢包重传等一系列连锁反应。
流量控制的方式是接收方的响应报文会携带自身接收滑动窗口大小的信息。若接收方滑动窗口大小为 0,则发送方停止发送数据。
(流量控制影响接收方的滑动窗口大小)
1.4 拥塞控制【基于慢启动】
拥塞控制解决的是整个网络的流量问题。拥塞控制是避免连续发包导致的网络拥塞,也避免网络拥塞时,突然出现较大量的数据,导致网络崩溃。
拥塞控制方式是在发送端设置一个拥塞窗口值,并采用慢启动机制。慢启动即将这个拥塞窗口大小设置为 1,之后每收到一次确认应答,拥塞窗口的值加 1。发送滑动窗口大小=min(拥塞窗口大小,接收方的接收滑动窗口大小)。
(拥塞控制基于慢启动机制,影响发送方的滑动窗口大小)
总结:
滑动窗口的引入是为了提高发送端数据的传输,以及数据报文有序性的保证。但是滑动窗口的大小受流量控制 及 拥塞控制的影响,滑动窗口的大小是二者保证基础下的最小值。流量控制解决的是端到端发送流量大小的问题,拥塞控制解决的是整个网络的数据注入大小问题。之所以引入流量控制,是因为当接收方接收缓冲区满,而发送方大量发送数据给接收方,接收方无法接收,会导致不断的丢包,重传等,造成网络拥挤。拥塞控制解决的是更宏观的问题,是整个网络的流量数据的问题。防止某个发送方突然发送大量的数据,导致网络崩溃。
1、TCP 与 UDP 的区别
1.1 连接性与可靠性
TCP 提供的是面向连接的、可靠的传输服务,而 UDP 提供的是面向无连接、不可靠的传出服务。
1.2 有界性
- TCP 提供的是面向字节流服务,无报文边界。因此会出现拆包与粘包现象。字节流服务,即 TCP 报文是流式结构,发送一次的数据大小依赖于发送缓冲区。若一次发送的数据大于发送缓冲区大小,TCP 会将其拆开(拆包现象);反之,TCP 会等待其他数据进来,等待缓冲区大小大于一定程度构成报文一并发送(粘包现象)。
- UDP 面向报文,通过报文边界来区分不同的报文。UDP 一次发送一个报文。
1.3 传播速度
TCP 由于请求应答机制、超时重传机制的存在,传播速度慢;UDP 传播速度快。
1.4 应用场景
TCP 应用于可靠性要求较高,而实时性要求不高的场景。UDP 应用于可靠性要求不高,但实时性要求较高的场景,如视频传输等。


简述 TCP 可靠性保证
TCP 主要提供了检验和字段、序列号/确认应答、超时重传、滑动窗口控制等方法实现了可靠性传输。
1)检验和:通过检验和的方式,接收端可以检测出数据是否有差错和异常,若有错误,则直接丢弃 TCP 段,。
2)序列号/确认应答:
3)超时重传:TCP 可靠性中最重要的一个机制是超时重传。TCP 要求在发送端每发送一个报文段,就启动一个定时器并等待确认消息,若在规定时间内没收到对方返回的确认消息,TCP 会认为数据未正确达到对方,而进行数据重传;
4)滑动窗口控制:滑动窗口控制解决的是超时重传效率低下的问题。超时重传需要一个包接一个包地发送。而滑动窗口控制机制保证了窗口内的数据包无需等待确认应答就能依次发送,从而提高了发送效率。



TCP 面向字节流 所以引入拆包与粘包现象。
什么时候发生拆包现象:当要发送的数据报大小大于缓冲区大小,则需要拆包。
什么时候发送粘包现象:当要发送的数据报大小小于缓冲区大小,并且多个数据报在缓冲区里一起发送。

简述 TCP 的 TIME_WAIT,为什么需要这个状态?
1)概念:TIME_WAIT 也称为 2MSL(Maximum Segment Lifetime,最大生存时间),它是任何报文丢弃在网络内的最长时间。
2)使用目的:理论上 4 个报文都发送完毕,就可以直接进入 CLOSE 状态。但是网络是不可靠的,有可能最后一个 ACK 丢失。 TIME_WAIT 状态就是用来重发可能丢失的 ACK 报文。
谈谈 TCP 的粘包和拆包
TCP 是面向字节流的,它不在字节流中插入边界标识符号。所以一个完整的包可能被 TCP 拆分成多个包进行发送,也有可能多个小的包封装成一个大的数据包发送。这就是TCP 的粘包和拆包问题。
谈谈 TCP 与 UDP 的区别
1)基于连接 VS 无连接
2)TCP 是可靠性传输协议,提供交付保证,若传输过程中数据丢失,将会重传;
UDP 不可靠,不提供任何交付保证【应用场景:实时视频、网游】
3)TCP 保证了消息的有序性,UDP 不提供;
4)数据边界
TCP 面向字节流,无数据边界;UDP 的数据包单独发送,因此包与包之间有明确的边界。
5)传播速度
TCP 传播速度慢;UDP 传播速度快【应用场景:实时视频、网游】
6)发送消耗
TCP 是重量级协议,UDP 是轻量级协议。因为 UDP 传输的信息不承担任何间接创造连接,及保证信息。
7)TCP 数据报头大,UDP 数据报头小;
8)流量控制:TCP 有流量控制,UDP 无流量控制
9)应用场景:
TCP 适合需要高可靠且对传输时间要求不高的应用,被应用于金融领域;
UDP 适合实时视频的传输、网游实时数据的传输,被应用于游戏和娱乐场所。


谈谈服务器如何判断客户端断开了连接?
keep-alive 机制
1)【TCP 内部机制】采用 keep-alive,如果一段时间客户端无发送数据给服务端,服务端会发送一个探测报文给客户端,若多次尝试后,客户端均无应答,则断开连接;
什么是 TCP 保活机制?它的作用是什么?
TCP 的 keep-alive 是由TCP层(内核态)实现的,称为 TCP 保活机制。若建立 TCP 连接的双方在一段时间内未通信数据,则会触发保活机制,即服务端会发送探测报文。若连接正常,客户端会发送响应报文,服务端收到响应报文后会重置 TCP 的保活时间。若多次尝试后,未收到客户端的应答,则服务端会关闭此条 TCP 连接。
谈谈端到端、点到点的区别
端到端通信建立在点到点通信基础之上,它是由一段段的点到点通信信道构成的。
端到端通信是针对传输层来说的,点到点通信是针对数据链路层或网络层说哦。

谈谈 HTTP 中的 Referer 头概念及作用
1)概念:HTTP Referer 是 header 的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理
2)作用:
2-1)防盗链:可以它能够个判断 referer 来达到只允许自身网站才能访问自身的图片;
2-2)防御 CSRF:比对HTTP 请求的来源地址,如果Referer中的地址是安全可信任的地址,那么就放行




http 2.0 的 IO多路复用理解:
HTTP/2 的多路复用是指在一个连接中并发多个请求或回应,而不用按照顺序一一对应。例如服务端收到客户端 A 和 B 的 2 个请求,若 A 请求处理过程非常耗时,就会先回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。






HTTPS 包括对称加密和非对称加密过程。
服务端向 CA 申请一套证书公钥和证书私钥,当客户端第一次向服务端发起请求的时候,服务端将证书公钥返回给客户端,客户端通过 SSL 算法判断证书公钥的合法性。若公钥合法,则生成一个随机序列,称为密文。用证书公钥对密文加密生成密钥,将密钥返回给服务端。服务端用证书私钥解密(非对称加密),获取密文。然后将返回信息用密文进行对称加密,并返回给客户端,客户端用密文解密(对称加密),获得正常的明文信息。
(总结)身份认证用非对称加密算法,内容加密用对称加密算法。

参考:https://blog.51cto.com/u_15283585/5156756




1、A 网站让用户跳转到 GitHub。
2、GitHub 要求用户登录,然后询问"A 网站要求获得 xx 权限,你是否同意?"
3、用户同意,GitHub 就会重定向回 A 网站,同时发回一个授权码。
4、A 网站使用授权码,向 GitHub 请求令牌。
5、GitHub 返回令牌.
6、A 网站使用令牌,向 GitHub 请求用户数据。



HTTP 响应头(Reponse Headers)有哪些报文段?
1)Cache-Control:缓存控制
2)Content-Encoding:报文编码方式
3)Content-Length:报文长度

HTTP 请求头(Request Headers)有哪些报文段?
1)Connection:连接方式 (Keep-alive)
2)Cookie:包含 token
3)Referer:指示发起这个请求的上一个页面
4)Host:服务端地址

RESTFUL 风格
1)RESTFUL 最常用的数据格式是 JSON,具有简单、易读、易用;
2)URI定位资源 与 操作区分开;
3)RESTFUL 是面向资源的,每一个资源都有一个 URI(唯一资源定位符),由于资源是一个东西,因此只能有动词,不能有名词,并且推荐用复数;
4)请求方式:GET; POST; PUT; DELETE
小林 —— 图说网络
基础篇
应用层协议:HTTP、FTP、DNS(域名转换请求协议)
HTTP 响应头(Reponse Headers)有哪些报文段?
1)Cache-Control:缓存控制
2)Expires:缓存的过期时间
3)Content-Encoding:报文编码方式
4)Content-Length:报文长度
5)Content-Type:内容类型

HTTP 请求头(Request Headers)有哪些报文段?
1)Connection:连接方式 (Keep-alive)
2)Cookie:包含 token
3)Referer:指示发起这个请求的上一个页面
4)Host:服务端地址
为什么需要 TCP/IP 协议?
为了兼容多种多样的进程进行通信,需要协商出一套通用的网络协议。
TCP 报头有哪些字段?
1)源端口;2)目的端口;3)序号;4)确认号;5)请求同步标志位 SYN;6)确认标志位 ACK;7)滑动窗口大小;8)检验和 等 20 个字段

IP 报头有哪些字段?
1)IP 协议版本(IPv4/IPv6);2)首部长度;3)报文总长度;4)源地址;5)目的地址

IP 协议的寻址与路由功能
1)【寻址——子网掩码】IP 地址划分为网络号、主机号。将IP 地址与子网掩码做按位与,就得到网络号,剩余就是主机号。
2)【路由】路由器寻址工作中,就是要找到目标地址的子网,找到后进而把数据包转发给对应的网络。
数据链路层——以太网
以太网就是一种在局域网内,把附近的设备连接起来,使他们进行通讯的技术。
每一层都会添加一个头部字段。

Linux 接收网络包的流程 —— socket 定位基于四元组
传输层取出 TCP 头或UDP 头,根据四元组【源IP、源端口、目的IP、目的端口】作为标识,找出对应的Socket,并把数据放到 Socket 的接收缓冲区。
最后,应用层程序调用 Socket 接口,将内核的 Socket 接收缓冲区的数据 [拷贝] 到应用层的缓冲区,然后唤醒用户进程。

Linux 发送网络包的流程
应用程序调用 socket(),陷入内核态,内核申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存【用户态拷贝到内核态】。当 sk_buff 的数据发送到网卡时,会 sk_buff 的内存会自动被释放掉。若使用 TCP 传输协议发送数据,内核会先拷贝一个新的 sk_buff 副本,以支持丢失重传。
考点:发送网络数据的时候,涉及几次内存拷贝操作?
总共 2 次内存拷贝。
第 1 次:调用发送数据的系统调用的时候,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存。【用户态拷贝到内核态】
第 2 次:如果使用 TCP 协议,为了支持超时重传,需要拷贝一份副本。
==================================================================================================
HTTP 篇
GET 和 POST 方法的安全性与幂等性
”安全性“是指请求方法不会破坏服务器上的资源;
”幂等性“是指多次执行相同的操作,结果都是相同的。
· GET 方法是安全且幂等的:所以可以对 GET 请求的数据做缓存。
· POST 方法既不安全也不幂等:例如每次 POST 都是对某个字段加 1,多次执行后肯定不是安全也不是幂等。
HTTP 2 种缓存实现方式:
· 强制缓存 【200,使用缓存的决定权在浏览器】
强制缓存决定是否使用缓存的主动权在于浏览器这边,只要浏览器判断缓存没有过期,就可以直接使用本地缓存。如返回的响应报文中使用 Status Code:200 (from disk cache) 就是使用了强制缓存
· 协商缓存【304,若过期,浏览器再次向服务器发起请求并携带本地缓存的摘要,若服务器的请求内容与浏览器本地缓存相同,则返回304,说明虽然本地缓存过期了,但是内容没变,依然可以使用。否则返回最新内容】
若响应码是 304 就是使用协商缓存,服务器告诉浏览器可以使用缓存。
浏览器发现本地资源缓存过期时,向服务器再次发起请求时在请求的 Etag 头部带上第一次请求的响应头部中的摘要,这个摘要就是唯一标识响应的资源。服务器收到请求后,会将本地资源的摘要与请求中的摘要做比较。若相同,则仅返回 304,告诉客户端缓存依然有效;否则返回最新资源。
HTTP/1.1 相比 HTTP/1.0 提高了什么性能?
· 使用长连接改善了 HTTP/1.0 短连接造成的性能开销;
HTTP/2 相比 HTTP/1.1 提高了什么性能?
· 使用 HTTPS 协议,提高了通信的安全性;相比 HTTP/1.1 纯文本形式的报文,HTTP/2采用的是二进制格式。
· HTTP 请求多路复用,使得请求无需串行处理,解决了 HTTP 层面请求队头阻塞的问题。HTTP 多路复用是基于数据流机制,每个请求或应答的所有数据包称为一个数据流。每个数据流有一个独一无二的 Stream ID,接收端通过 Stream ID 有序组装 HTTP 信息。
· 服务器推送。在客户端访问 HTML 时,服务器可以直接主动推送 CSS 文件,减少消息传递的次数。
HTTP/2 的缺陷
HTTP/2 依然存在 TCP 层面的队头阻塞问题。
HTTP/2 是基于 TCP 协议来传输数据的。而 TCP 要求收到的字节数据是完整且连续的,才会将数据返回给 HTTP 应用。若某个字节数据未到达,后接收到的数据只能存在内核缓冲区。所以 HTTP/2 依然存在 TCP 层面的队头阻塞问题。
HTTP/3 相比 HTTP/2 提高了什么性能?
· 使用 UDP 连接,确保不会出现队头阻塞问题,且通信更加快速
HTTP/1.1 如何优化?
· 尽量避免发送 HTTP 请求
解决办法是使用缓存机制,包括强制缓存及协商缓存。
· 在需要发送 HTTP 请求时,减少HTTP 请求次数
解决办法是通过代理服务器减少重定向请求次数、通过合并几个请求资源来合并请求应答、按需发送请求。
· 减少服务器的 HTTP 响应的数据大小
解决办法是使用压缩编码方式
RPC 和 HTTP 有什么区别?(使用 RPC 需要设计哪几个模块)
RPC 和 HTTP 都是基于 TCP 连接的。RPC 协议较早,HTTP 协议较晚。
** 服务发现 **
【HTTP 协议需要对方的IP和端口,RPC 无需知道,因为有中间服务保存对方的IP和端口】
客户端要与服务器建立连接,首先要知道服务器的 IP 地址和端口,找服务对应的 IP 地址和端口的过程就是服务发现。
HTTP 可以通过 DNS 服务(本质也是一种中间服务)解析背后的 IP 地址,且默认是 80 端口。而RPC 一般会有专门的中间服务去保存服务名和 IP 信息。想要访问某个服务,就去中间服务去获得 IP 和端口信息。
** 传输的内容(编码解码方式)**
【HTTP 传输的是字符串,RPC 传输的是各种序列化数据】
HTTP 采用的是超文本协议,传输的内容是字符串。
而 RPC 定制化程度更高,可以采用其他更好的序列化协议去保存结构体数据。
TCP 3 大特点:面向连接、可靠、基于字节点
建立一个 TCP 连接是需要客户端与服务器端达成 3 个共识:
1)Socket:由 IP 地址和端口号组成;
2)序列号:用来解决乱写问题等;
3)窗口大小:用来做流量控制
如何确定一个 TCP 连接?
TCP 四元组可以唯一确定一个连接:源地址、源端口、目的地址、目的端口
一个服务器的 TCP 连接的最大连接数是多少?
由于有多个客户端 IP ,每个 IP 有多个端口,其理论值计算公式如下:
最大 TCP 连接数 = 客户端的 IP 数 x 客户端的端口数
但是由于以下 2 个因素影响,现实远远达不到这个理论最大值:
1)文件描述符限制。每个 TCP 连接就是一个文件,要收到服务端文件描述符个数的限制。
2)内存限制。每个 TCP 连接毒药占用一定内存,而内存是有限的。
========================================================================
TCP 篇
端口的作用是什么?TCP 和 UDP 可以使用同一个端口吗?
传输层 端口号 的作用,是为了区分一个主机不同应用程序的数据包。当主机收到数据包后,可以在 IP 包头的协议号字段知道该数据包是 TCP/UDP,从而交付给 TCP/UDP 处理。
========================================================================
IP 篇
IP 协议相关技术
· DNS 域名解析
· ARP 与 RARP 协议:IP 与 MAC 地址的转换
· DHCP(Dynamic Host Confuguration Protocol,动态主机配置协议) 动态获取 IP 地址
动态分配 IP 的 4 个步骤
1)由于客户端刚开始没有 IP 地址,所以它使用 UDP 广播 DHCP 发现报文,目的地址是广播地址 255.255.255.255,并且使用 0.0.0.0 作为源 IP 地址。
2)DHCP 服务器收到 DHCP 发现报文就向客户端发送 DHCP 提供报文做出响应。
3)客户端收到 DHCP 提供报文后,向服务器发送 DHCP 请求报文,回显配置的参数;
4)最后,服务端用 DHCP 应答报文对 DHCP 请求报文进行响应,应答所要求的参数。
· NAT 网络地址转换
将私有 IP 地址转换成公有 IP 地址。
· ICMP (Internet Control Message Protocol,互联网控制报文协议)
如果数据包在传输过程中出现异常,由 ICMP 报告异常的原因,并以此调整传输策略。
ICMP 主要功能:确认 IP 包是否成功送达目标地址、报告发送过程中 IP 被丢弃的原因和改善网络设置等。
Linux 发送网络包的流程
· 1)用户程序调用发送数据包的接口,程序由用户态陷入到内核态,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区。
· 2)网络内核栈从 socket 发送缓冲区中取出 sk_buff,并按照 TCP/IP 协议栈从上到下逐层处理。若使用 TCP 传输协议发送数据,还得先拷贝一个新的 sk_buff 副本。 原因:sk-buff 在调用网络层,最后到达网卡发送完成的时候,sk_buff 会被释放掉。而TCP需要支持超时重传,在收到对方的确认报文 ACK 前,这个sk_buff 不能被删除。内核在每次调用网卡发送的时候,实际上传递的是 sk_buff 的一个拷贝,等收到 ACK 再真正删除。
· 3)协议栈采用分层结构,上层向下层传递数据时,需要增加包头,下层向上层传递时需要去掉报头,每层之间传递,都需要修改 sk_buff 中 data 的指针。
比如:
· 当接收报文时,从网卡驱动开始,通过协议栈层层往上传送数据报,通过增加 skb->data 的值,逐步剥离协议首部;
· 当发送报文时,创建 sk_buff 结构体,数据缓存区的头部预留足够的空间,用来填充各层首部,在经过各下层协议时,通过减少 skb->data 的值增加协议首部。
· 添加完 TCP 头部后,传输层工作完成,交给网络层。网络层做的工作包括:选取路由(确认下一跳的 IP)、填充 IP 头、netfilter 过滤【对于不同的协议(IPv4、IPv6 或 ARP 等),Linux 内核网络栈会在该协议栈数据包处理路径上的预设位置触发对应的 hook。】,对超过 MTU 大小的数据包进行分片。处理完这些工作交给网络接口层处理。
· 网络接口层通过 ARP 协议获得下一跳的 MAC 地址,然后对 sk_buff 填充帧头和帧尾,接着将 sk_buff 放到网卡的发送队列中。
· 最后,会触发软中断,告诉网卡驱动程序,有新的网络包需要发送。驱动程序会从发送队列中读取 sk_buff ,将 sk_buff 挂到 RingBuffer 中,接着讲 sk_buff 数据映射到网卡可访问的 DMA 区域,最后触发真实的发送。
· 当数据发送完成后并收到这个 TCP 报文的 ACK 应答时,网卡设备会触发一个硬中断来释放 sk_buff 内存和 RingBuffer 内存。
发送网络数据的时候,涉及几次内存拷贝操作?
· 第 1 次:调用发送数据系统调用,将用户发送数据从用户态拷贝到内核态的 sk_buff 内存,并加入到发送缓冲区;
· 第 2 次:(TCP)从传输层进入网络层的时候,每一个 sk_buff 都会被克隆出一个新的副本。只有等收到这个数据包的 ACK 时,才会释放原始的 sk_buff
· 第 3 次:当 IP 发现 sk_buff 大于 MTU 时,会再申请额外的 sk_buff ,并将原来的 sk_buff 拷贝为多个小的 sk_buff。
· sk_buff
内核使用 sk_buff 表示报文。sk_buff 结构本身不存储报文内容,它通过多个指针指向真正的报文内存空间。在内核协议栈各层间,传递的是 sk_buff 结构,并且在传递过程,内核只需要调整 sk_buff 中的指针位置。【这样做的是提高数据在上下层之间的传递效率】
· 补充:Netfilter —— Linux 内核网络数据包处理框架
· IP tables
保活机制/心跳包机制知识点
1.1 什么是心跳包机制?有什么用处?
客户端与服务端通信都是基于 socket 的。若此套接字断开,则双方无法继续接发数据。心跳包机制就是判断对方的 socket 是否可用的机制。
1.2 双方通信确认对方是否在线可以在哪些层面进行设置?
可以在 TCP 协议层通过 SO_KEEPALIVE 实现,也可以在应用层通过心跳包机制实现。TCP 有 SO_KEEPALIVE 属性,若设置了该属性,那么 TCP 会在一定的时间内发送设置的次数的探测包,一般系统默认是 2 小时发送一次探测包(探测包就是一个自定义的结构体),以确保双方可以保持连接,或者说探测包机制是保证了长连接。
1.4 说说服务器在哪些情况下认为客户端断线?
服务器会为每个客户端维护一个定时器,若收到客户端的正常报文或心跳包,会将定时器的计数器归零,若计数器达到某个阈值,则认为客户端断开;
1.5 说说客户端在哪些情况下认为服务端断线?
通过 TCP 的请求应答机制。或者 TCP 的保活机制。
1.6 心跳检测是由一方检测,是哪一方呢?还是双方检测,为什么呢?
心跳检测是由双方进行检测。在高并发情况下,一般是由客户端隔断时间发送心跳包给服务端,服务端会维护一个定时器,若在一定时间内,收到客户端的报文或探测包会重置定时器的时间,若定时器时间超过一定阈值,则会断开连接。
1.7 TCP 的 keepalive / 心跳包机制 就一定能保证对方是否保持连接吗?
心跳包机制无法检查到机器断电、网线被拔等原因造成的对方不在线(心跳包发送间隔期)。如果服务器断电,再重新启动时,收到某个客户端的 TCP 报文,但是服务端维护的 TCP 连接列表里并无此连接,则会想对端发送 RST 报文。
1.8 什么是 RST 报文
RST 报文即复位报文。正常关闭/优雅关闭 TCP 连接需要通过 4 次挥手,对于异常关闭 TCP 连接(非优雅关闭)需要借助复位报文 RST 报文。若服务器想非优雅关闭 TCP 连接,就发送一个 RST 报文,此时若服务器的发送缓冲区还存有发送数据,则直接丢弃剩余发送数据,直接向对方发送 RST 数据报。然后服务端释放连接,客户端收到 RST 报文不必发送应答报文,直接释放连接。
1.9 RST 报文除了在非优雅关闭会发送,还会在哪些情况下使用呢?
1)非优雅关闭 TCP;
2)客户端访问服务器未对外提供服务的端口;
3)程序崩溃。如果 C/S 某端在交互过程中出现程序崩溃,那么该方会向对方发送 RST 报文,告之对方直接释放连接;
4)若服务端收到某个 TCP 报文,但是并未在自己维护的 TCP 列表中找到对应的 TCP,则直接向对方发送 RST 包,告知对方释放连接;
5)长期未收到对方的确认报文
TCP 有个请求应答机制,若 C/S 某端未收到对方的确认报文,会进行超时重传。若进行多次超时重传后,仍未收到对端的应答报文,则会向对方发送 RST 报文。
部分重要的 SOCKET 选项
设置 socket 的 属性函数
setsockopt(int sockfd, int level, int option_name, const void* option_value, socklen_t option_len)
主要讲讲 option_value
1)SO_REUSEADDR 选项
TCP 断开连接四次挥手 主动断开连接会进入 time_wait 状态,这个状态会持续 2MSL。在完全断开前,不允许重新监听。为了实现对多个连接进行监听,使用 SO_REUSEADDR。
2)SO_RCVBUF 和 SO_SNDBUF 选项
指定 TCP 接收缓冲区和发送缓冲区的大小
3)SO_LINGER 选项
https://blog.csdn.net/weixin_33971130/article/details/88923275
SO_LINGER 在优雅关闭连接中会用到。SO_LINGER 是设置延迟关闭的意思,等待套接字发送缓冲区的数据发送完成,再发送 FIN 包。
· 如果不设置 SO_LINGER 选项,当发送方调用 close() 后,close() 会立刻返回,TCP 连接断开。它不管发送缓冲区剩余的数据是否会到达对端。具体措施是将缓冲区的数据直接丢弃,并发送 RST 包给对端。

· 如果设置了 SO_LINGER 选项,会保证先将缓冲区的数据发送完后,再发送 FIN 报文。在L_LINGER 这段时间收到对发送数据及 FIN 的确认后, close() 才返回。可以将 L_LINGER 的数值调大,就能走完 4 次挥手流程。

4)SO_KEEPALIVE
SO_KEEPALIVE 设置保活机制,检测对方是否在线。默认设置 2 小时内发送一个保活探测分节。但是:UNIX 网络编程一般不使用 TCP 的保活机制,而是在应用层实现心跳包机制。
为什么 TCP 层有保活机制,还需要在应用层实现心跳包机制呢?
TCP 协议的 SO_KEEPALIVE 的缺点如下:
1)【在服务端设置保活】一般而言,TCP 的 SO_KEEPALIVE 是在服务端设置的。因为服务端的寿命比客户端长。如果由客户端来实现,客户端宕机,服务端就维持一个无用的 TCP 连接,浪费系统资源。
2)【TCP keepAlive 只能检测保活,无法检测连接是否可用】KeepAlive 只能检测连接是否存活,而不能检测连接是否可用。TCP keepalive 是由操作系统负责探测,即使应用进程死锁或阻塞,操作系统也会如常收发 TCP keepAlive 消息。对方无法知道连接是否可用
应用层是如何实现心跳包机制的?
一般而言,在定时器即将达到阈值时,会发送一个比较小的心跳包给对方,如果对方有回复,则重置定时器,否则直接进行连接超时处理。
服务器如果主动断开,客户端还会发送一个心跳包吗?发心跳包的具体机制了解过吗?
如果服务端主动调用 FIN 分节给客户端,客户端之后就不会再发心跳包了。心跳包一般是在双方通信空闲时期才会发送的。
谈谈序列号的作用?序列号是怎么初始的?有哪些初始算法?数据包的序列号可以从 0 开始吗?
1)序列号是用来累计标识已发送的数据包的个数。通信双方在建立连接时都会初始化序列号 ISN。应答报文的应答序号表示期望发送方下次发送的请求报文序号。
2)序列号是随机生成的,随机生成算法如下:
ISN = M+F(四元组)
其中,M 是个计时器,F 是对四元组的一个哈希值
3)由于通信双方是通过 TCP 四元组标识一个 TCP 连接的。如果某端 A 由于某种原因中断了连接,再次上线时,与服务端重新确立连接。为了防止中断前在网络上未到达对端 B 数数据后续依然被服务端接收,造成数据混乱,一般都会通过随机算法初始化序列号,而不从 0 开始。
谈谈初始化序列号的目的
由于通信双方是通过 TCP 四元组标识一个 TCP 连接的。如果某端 A 由于某种原因中断了连接,再次上线时,与服务端重新确立连接。为了防止中断前在网络上未到达对端 B 数数据后续依然被服务端接收,造成数据混乱,因此,需要初始化序列号。
谈谈 TCP 有哪些首部字段?字段中又有哪些标志位?
1)源端口号;2)目的端口号;
3)TCP 首部字段;4)SYN|ACK|FIN|RST;5)滑动窗口大小
6)校验和
谈谈什么是滑动窗口,为什么要有滑动窗口?
· 讲滑动窗口要讲请求应答机制及超时重传机制。发送端发了一个报文给对方,只有收到对方对这个报文的确认,才能发下一个报文。若在规定时间内未收到应答报文,就会开启超时重传。为了解决这种低效率问题,就提出滑动窗口的概念。
· 窗口的大小就是在无需等待确认包的情况下,发送端还能发送的最大数据量。滑动窗口机制使用了大量的缓冲区来保证超时重传。
· 滑动窗口的大小受流量控制及拥塞控制的影响,是二者允许传输数据的最小值。
跨主机通信除了 socket 还有哪些方式?
除了 socket,应该就是 docker 容器的跨主机方式。

浙公网安备 33010602011771号