物理层
- 奈奎斯特定理 理想低通道下的极限数据传输率=2Wlog2V; W 信道带宽、V每个码元的离散电平数(离散点平可以表示多少信息);
- 香农定理 信道极限传输速率=\(w*log(1+ \frac{S}{N})\); \(\frac{S}{N}\):信噪比;
- 编码转换成数字信号
- 非归零编码: 0/1
- 曼彻斯特编码:1 都是上升沿,0都是下降沿
- 差分曼彻斯特编码:若码元为1,前半个码元的电平保持不变,若码元为0,变化。
- 数据传输的方式
- 电路交换(物理连线)
- 报文交换(报文不设上限,存储转发)
- 分组交换(讲一个报文拆分成很多组,每一组都单独传输,加快传输的速度,降低时延,增加可靠性)
- 设备
- 中继器:放大信号
- 集线器(hub):一对多放大器
数据链路层
- 差错校验:循环冗余码(CRC) 原数据报M(x)、预先确定的多项式G(x)
- 流量控制:停止-等待协议、滑动窗口(大小固定)流量控制、回退N协议、选择重传协议
- 随机访问介质访问控制:
- ALOHA:立即发送、收到确认:结束、未收到:等待随机一段时间之后再传输。
- 时隙ALOHA协议:同步时间,将时间分段,只能在时隙开始的时候发送帧。
- CSMA:
- 1-坚持CSMA:一直侦听信道,空闲立即发送、冲突等待一段时间之后,重新侦听空闲时发送。
- 非坚持CSMA:侦听信道,忙,等待随机事件再侦听,空闲立即发送
- p-坚持CSMA:侦听信道,忙,以可能性p发送,(1-p)推迟到下一个时隙。
- CSMA/CD(载波侦听碰撞检测):先听后发,边听边发(区别于CSMA协议),冲突停发,随机重发(时间长度从指数增长的集合中随机取出)。要求数据有最小长度。使得发送时间段内不侦听到冲突,不会发生冲突。
- CSMA/CA(载波侦听碰撞避免):预约信道(A 发送之前预约信道),ACK 确认(A接收到其他站点的确认帧之后,确认预约成功。否则重新预约,直至次数达到阈值发送失败)
- 令牌传递协议
- 环形网络,传输令牌,拿到令牌的机器有权力不转发令牌进行数据传输,
- 以太网链路层数据帧格式
- Ethernet V2:无连接的数据链路层的服务
- IEEE 802.3 面向连接的数据链路层的服务
- 生成树协议 可以避免网络环路,可以实现线路备份。为了防止广播风暴
- 端口聚合 也可以防止广播风暴,提高网络带宽,实现线路备份
- VLAN 虚拟局域网,
- 基于端口的VLAN划分
- 基于Mac地址的VLAN划分
- 基于协议的VLAN划分,例如IP协议和IPX协议
- 基于子网的VLAN划分,会造成网络开销增大
- PPP协议
- 设备
- 交换机:Mac地址与端口相对应;
网络层(主机之间)
相关名词
IP、NAT(网络地址转换)、ARP(地址解析协议(IP->mac地址映射表))、DHCP(给主机动态分配IP地址)、ICMP(网际控制报文(差错报告和询问报告,ping))、IGMP(组播管理协议)
路由算法
- RIP 距离矢量路由选择协议,将自己的路由信息通过UDP传输到自己的相邻节点
- OSPF 链路状态路由算法(测试相邻节点,通过IP传播到所有的节点、使用Dijsktra算法)
- BGP 边界路由算法(属于应用层协议,基于TCP),跨区域传输时,边界路由负责转发 边界网关协议
IPV6
地址由ipv4的32位拓展到128位 端口号16位
IP地址的分类
- A类:0开头,一个字节的网络地址,三个字节的主机ID,有\(2^{8-1}-2\)个网络号,每个网络号有\(2^{24}-2\)个主机
- B类:10开头,两个字节的网络地址,两个字节的主机ID,类推
- C类:110开头,三个字节的网络地址,一个字节的主机ID
- D类:1110开头,组播地址
网络层分片
链路层对数据帧长度有要求,也就是MTU
具体实现
在IP分片时,通过在IP数据报首部设置标识、标志、片偏移的信息来帮忙目标系统对分片重组。
比如传输10k的数据,IP层先生成一个长度为10k的IP Packet, 比如其IP头ID=1,然后开始做Fragment操作,
标识:10个分片一样的,都是1
标志位:DF表示是否可以分片;MF除了最后一个分片是0,其它都是1
片偏移:0,125,250…
路由
根据路由器学习路由信息、生成并维护路由表的方法包括直连路由(Direct)、静态路由(Static)和动态路由(Dynamic)。
直连路由:路由器接口所连接的子网的路由方式称为直连路由。其由是由链路层协议发现的,一般指去往路由器的接口地址所在网段的路径,该路径信息不需要网络管理员维护,也不需要路由器通过某种算法进行计算获得,只要该接口处于活动状态(Active),路由器就会把通向该网段的路由信息填写到路由表中去,直连路由无法使路由器获取与其不直接相连的路由信息。
非直连路由:通过路由协议从别的路由器学到的路由称为非直连路由;分为静态路由和动态路由;
传输层(进程之间)
UDP
在IP的基础上增加了复用、分用和差错检测。面向报文
- 差错校验
- 发送方:添加伪首部,校验和默认为0,分成16位一组不足部分补0,相加求和得到结果,求二进制反码,放入校验和的位置
- 接收方:添加伪首部,分组,补0,相加结果全为1
- 无需建立连接、无连接状态、分组首部开销小、低延迟容忍丢包。
- 数据报处理的最小单位,不可拆分(面向报文的含义)
- 应用:DNS(port53)快速、轻量、高效。反向代理,根据负载分配IP
- 应用:高效的文件传输
- UDP,对文件分片
- 纠错 & 重传
- 零拷贝(参考操作系统的文件IO)
TCP
特点
TCP的主要特点是面向连接、基于字节流、可靠的,这也可以理解是基于网络层之上进一步提供的功能。
面向连接:TCP必须通过三次握手建立连接之后才能开始数据的读写,且连接是全双工的,即双方的数据读写可以通过一个连接进行。完成数据交换之后,必须通过四次挥手断开连接并释放相应的系统资源。
基于字节流的:应用程序对数据的发送和接受是没有边界限制的。TCP模块中有TCP发送缓冲区和接受缓冲区的概念。发送端连续执行多次写操作时,TCP模块将这些数据放入TCP发送缓冲区,之后以TCP报文段的形式发出。也就是TCP模块发送的TCP报文段的个数与应用程序执行的写操作次数之间没有固定的数量关系,读操作同理。但UDP不同,接受端必须指针每一个UDP数据报执行读操作,否则就会丢包,并且,如果用户没有指定足够的应用程序缓冲区来读取UDP数据,UDP数据将被截断。
可靠的
- 通过超时重传,应答保证数据不会丢失;
- 通过校验和保证数据可靠;
- 通过序号、ACK、滑动窗口(发送应答机制)保证数据顺序性和有效性;
- 通过流量控制减轻接收方接收数据的压力;
- 通过拥塞控制减轻全局性的网络传输数据的压力。
TCP Header
TCP Header格式如下。针对其中一些容易忽视的知识点进行了整理
1 | 0 1 2 3 |
- Data Offset:由于TCP Header的长度上是可以变化的,所以需要Data Offset指明数据区开始的位置
- 控制位
- URG:紧急指针,在例如用户终止数据传输时有效
- PSH:接收方应该立即将现在缓存区的内容提交给上层
- RST:重新建立连接请求
- Window:用于流量控制的窗口大小
- Checksum:为什么有IP的校验,还需要有TCP的校验?主要是防止网络设备的程序BUG或者内存故障,造成的数据错误。这有可能是IP校验不出来的
- TODO,看书
缩写解释
- MSL:允许包传输的最大时间(linux允许的时间是30s)
- TTL:在路由器间跳转的次数
三次握手
三次握手的是证明通信双方具有发送和接收功能
在三次握手过程中,如果发生丢包情况,采取的策略是不同的
- 第一个包,即A向B发送的SYN中途丢失,A会周期性超时重传,直到收到B的确认
- 第二个包,即B向A发送的ACK+SYN中途丢失,B会周期性超时重传,直到收到A的确认
- 第三个包,即A向B发送的ACK中途丢失,此时A发完ACK,单方面认为TCP为Established状态,而B没有收到ACK,认为TCP为Active状态
- 假定此时A有数据发送,B收到A的ACK+DATA,自然会切换为ESTABLISHED 状态,并接受A的DATA
- 假定此时B有数据发送,但无法发送,会一直周期性超时重传SYN+ACK,直到收到A的确认才可以发送数据
- 假定此时双方都没有数据发送,B会周期性超时重传,直到收到A的ACK,收到之后B的TCP 连接切换为 ESTABLISHED状态,双向可以发包
其他设计的缺陷
两次握手的问题
- 无法防止历史连接的建立(重复连接),无法可靠同步双方序列号
- 接收方无法确定发送方的接收能力
四次握手的问题
多余,没有必要
三次握手在OS中体现
在上述流程中,分析一下SYN攻击;SYN攻击指的是服务器短时间内响应大量请求的SYN报文但却没有收到对方的ACK应答造成的SYN接受队列占满,使得服务器无法为正常用户提供服务。其应对策略:
- 修改Linux内核参数
/proc/sys/net/ipv4/tcp_max_syn_backlog
,设置超出某一阈值后的SYN请求直接丢弃。 - 当SYN队列满之后,后续服务器收到的SYN包不进入SYN队列,而是直接计算出一个cookie值,再以SYN+ACK中的序列号返回客户端,服务器接收到客户端的ACK之后,检查其合法性,如果合法直接放入到Accpet队列,否则丢弃。
性能优化
客户端
比如在内网中通讯,根据网络稳定性和目标服务器的繁忙程度适当降低 SYN 重试次数,尽快把错误暴露给应用程序。tcp_syn_retries 字段设为 3
1
echo 3 > /proc/sys/net/ipv4/tcp_syn_retries
服务端
增加半/全连接队列长度,以提高连接数,设置 tcp_max_syn_backlog、somaxconn 为 1024
全连接队列长度取决于 somaxconn 和 backlog 之间的最小值,backlog 是 listen(int sockfd, int backlog) 函数中的 backlog 大小。改变了这两个参数后,要重启 Nginx/Tomcat 服务,因为半连接队列和全连接队列都是在 listen() 初始化的。
开启 syncookies ,以达到在不使用半连接队列的情况下成功建立连接,设置 tcp_syncookies 为 1
syncookies 的工作原理:服务器根据当前状态计算出一个值,放在己方发出的 SYN+ACK 报文中发出,当客户端返回 ACK 报文时,取出该值验证,如果合法,就认为连接建立成功。
调大 SYN+ACK 重发次数,以提高连接的成功率,设置 tcp_synack_retries 为 5
在服务端向客户端发送 SYN+ACK 之后,如果迟迟收不到客户端反馈的 ACK,会重发 SYN+ACK。当网络繁忙、不稳定时,报文丢失就会变严重,此时可以调大 SYN + ACK 的重发次数
将默认的丢失连接改为回复 RST,以告知客户端及时放弃连接请求,设置 tcp_abort_on_overflow 为 1
当全连接队列过载时, Linux 默认丢弃连接,客户端需要经过多次重试之后才会放弃连接。可以调整为服务器通过 RST 复位报文主动通知客户端当前全连接队列过载,无法建立新连接。这时在客户端异常中可以看到很多 connection reset by peer 的错误。
不过通常情况下,应当把 tcp_abort_on_overflow 设置为 0,因为这样更有利于应对突发流量。当服务器上的进程只是短暂的繁忙造成全连接队列满,那么当全连接队列有空位时,再次接收到的请求报文由于含有 ACK,仍然会触发服务器端成功建立连接。
开启 TFO,以减少 TCP 连接建立的时延。设置 tcp_fastopen 为 3
在 Linux 3.7+ 内核,提供了 TCP Fast Open 功能。利用 Cookie,在第一次发起 HTTP GET 请求的时候,还是需要正常的三次握手流程,但是之后客户端再次向服务器建立连接,就可以绕过三次握手,这就减少了握手带来的 1 个 RTT 的时间消耗。不过,TFO 功能需要客户端和服务器同时支持。
四次挥手
其他设计的缺陷
为什么不是三次或者五次?
四次挥手是因为TCP是全双工通信的,前2次挥手用于关闭一个方向的数据通道,后两次挥手用于关闭另外一个方向的数据通道。实际上也可以通过3次挥手断开连接,但如果这么做,B发的是FIN+ACK,考虑服务器还有要向客户端发送数据的情况,此时B不能响应A的FIN 的请求,但不响应的话,A会认为B没有收到FIN,会一直重发FIN,引发不必要的FIN重传;而5次握手则存在释放连接速度过慢,影响传输效率的情况。(怎么能变成5次?😂
关于TIME_WAIT
等待两个MSL时间(最大报文生存时间)的原因
可靠地实现TCP全双工连接的终止。如果A对B的ACK丢失,B会超时重传FIN+ACK报文,此时A就可以在2MSL时间内收到并重传ACK,保证B能够正常进入关闭状态。
使旧数据包在网络因过期而消失。如果在连接断开之后,客户端端口复用又发起一个TCP连接,这时上一次TCP连接里已失效的数据包到达,会被第二次TCP连接接受,从而引起数据错乱。TCP作为一个可靠传输协议,绝不允许这种情况出现。
等待两个MSL时间的缺陷 * 对文件描述符的占用。在高并发短连接的TCP服务器上,当服务器处理完请求后主动请求关闭连接,这样服务器上会有大量的连接处于TIME_WAIT状态,服务器维护每一个连接需要一个Socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用是有上限的,如果持续高并发,会导致一些连接失败。 * 对端口资源的占用。假设双十一天猫的服务器因为某些原因服务器进程挂掉退出了,由于是服务器主动关闭连接,因此会有TIME_WAIT状态存在,也就意味着服务器进程想立即重启,但是因为端口(可能是80)还被之前处于TIME_WAIT的连接占用着,服务起不来,如果TIME_WAIT状态维持60秒,60秒服务器都起不来,直接少了一笔巨款。
服务器上存在大量的TIME_WAIT如何应对? * 通过修改内核参数 tcp_max_tw_buckets 修改TIME_WAIT连接状态的上限值。 * 开启重用机制。设置套接字选项为SO_REUSEADDR 或设置内核参数 tcp_tw_reuse 达到端口复用的效果。 * 修改短连接为长连接。长连接比短连接从根本上减少了关闭连接的次数,减少了 TIME_WAIT 状态的产生数量。 * 由客户端来主动断开连接。如果业务场景允许的话。
四次挥手结束后,客户端和服务端会发生什么情况?
Server在收到Client的 ACK 之后,就进入 CLOSED 状态,经过撤销相应的传输控制块 TCB 后,就结束了这次的 TCP 连接。Client在经过 WAIT_CLOSE 之后,进入 CLOSED 状态。
一个TCB包含了数据发送双方对应的 socket 信息以及拥有装载数据的缓冲区。
性能优化
主动断开方
主动发起 FIN 报文断开连接的一方,如果迟迟没收到对方的 ACK 回复,则会重传 FIN 报文,重传的次数由 tcp_orphan_retries 参数决定。
当主动方收到 ACK 报文后,连接就进入 FIN_WAIT2 状态,根据关闭的方式不同,优化的方式也不同:
- 如果这是 close 函数关闭的连接,那么它就是孤儿连接。如果 tcp_fin_timeout 秒内没有收到对方的 FIN 报文,连接就直接关闭。同时,为了应对孤儿连接占用太多的资源,tcp_max_orphans 定义了最大孤儿连接的数量,超过时连接就会直接释放。
- 反之是 shutdown 函数关闭的连接,则不受此参数限制;
当主动方接收到 FIN 报文,并返回 ACK 后,主动方的连接进入 TIME_WAIT 状态。这一状态会持续 1 分钟,为了防止 TIME_WAIT 状态占用太多的资源,tcp_max_tw_buckets 定义了 TIME_WAIT 状态上限个数,超过时连接也会直接释放。
当 TIME_WAIT 状态过多时,还可以通过设置 tcp_tw_reuse 为 1,将 TIME_WAIT 状态的端口复用于作为客户端的新连接,注意该参数只适用于客户端。
被动断开方
被动关闭的连接方应对非常简单,它在回复 ACK 后就进入了 CLOSE_WAIT 状态,等待进程调用 close 函数关闭连接。因此,出现大量 CLOSE_WAIT 状态的连接时,应当从应用程序中找问题。
当被动方发送 FIN 报文后,连接就进入 LAST_ACK 状态,在未等到 ACK 时,会在 tcp_orphan_retries 参数的控制下重发 FIN 报文。
TCP状态机
重传机制
- 超时和冗余ACK(快速重传技术,接收方收到比期望大的报文的时候,发送对期望顺序得到的报文的ACK,发送接收到三次相同的ACK,确认报文丢失,进行重传)
- SACK,再接收到三次ACK之后,发送方不知道之后包的接受情况,所以可以采用SACK技术,将之后包的接受情况通过可选项传递给发送方,提高传输效率
流量控制
基础知识
- 是端到端的问题,解决的问题是:让发送方的发送速率不要太快,要让接收方来得及接受
- rwnd接收方连续接收的能力,cwn拥塞窗口,接收方的发送窗口为
min(rwnd, cwnd)
; - 对应的有Nagle算法
- 发送端尽量将数据组成较大的报文段发送出去,只在收到对前一个报文段的确认后才继续发送下一个报文段;
- 接收端采用推迟确认技术,等到接收缓存至少有一半空闲的空间或者达到最大报文长度时,接收方再发出确认报文,并向发送方通知当前的窗口大小。
性能优化
提升滑动窗口的上限
TCP 可靠性是通过 ACK 确认报文实现的,又依赖滑动窗口提升了发送速度也兼顾了接收方的处理能力。可是,在 TCP 报文头中的滑窗大小只占用2个字节,也就是滑动窗口最大值只有 64 KB,要想提升发送速度必须提升滑动窗口的上限,在 Linux 下可以通过设置 tcp_window_scaling 为 1 做到的,此时最大值可高达 1GB。
把缓冲区的上限设置为带宽时延积
滑动窗口定义了网络中飞行报文的最大字节数,当它超过带宽时延积时,网络过载,丢包严重。而当它小于带宽时延积时,无法充分利用网络带宽。因此,滑动窗口最好设置在带宽时延积左右。又因为内核缓冲区决定了滑动窗口的上限,缓冲区可分为发送缓冲区 tcp_wmem 和接收缓冲区 tcp_rmem,Linux 会对缓冲区动态调节,所以应该把缓冲区的上限设置为带宽时延积。
发送缓冲区的调节功能是自动打开的,而接收缓冲区需要把 tcp_moderate_rcvbuf 设置为 1 来开启。其中,调节的依据是 TCP 内存范围 tcp_mem。但需要注意的是,如果程序中的 socket 设置 SO_SNDBUF 和 SO_RCVBUF,则会关闭缓冲区的动态调整功能,所以不建议在程序设置它俩,而是交给内核自动调整比较好。
拥塞控制
基础知识
是一个全局性的过程,解决的问题是防止过多的数据注入网络,这样可使网络中的路由器或链路不至于过载
慢开始:每成功完成一次报文传输\(cwnd=cwnd*2\); 拥塞窗口成指数增长,直至\(cwnd\)达到阈\(ssthresh\)(\(cwnd\)超过阈值的时候,\(cwnd=sstresh\))
拥塞避免:慢开始之后开始使用拥塞避免算法,每成功传输一次报文,\(cwnd=cwnd+1\); 出现一次超时时,\(ssthresh=\frac{cwnd}{2}\); 出现拥塞后,\(sstresh=\frac{cwnd}{2}(不能小于2)\),重新设\(cwnd=1\),重新开始执行慢开始算法。(让路由器有充分的时间处理积压的分组)
快重传:收到三次重复ACK之后,立即重传。
快恢复:收到三次重复ACK之后,将\(sstresh=\frac{cwnd}{2}\)并将\(cwnd=sstresh\),开始执行拥塞避免算法。
注意这里的机制和遇到超时的机制的处理是有差别的。在不同的TCP实现版本上,这个具体的做法也是有差异的。
性能优化
Linux kernel 4.9+ 集成了 TCP BBR 算法。Google 的拥塞控制算法 BBR 以测量带宽、时延来确定拥塞,在缓冲队列(指网络硬件设备上的)刚出现堆积时就拥塞控制,而不是像传统拥塞控制算法在缓冲队列溢出的时候才控制。同时,BBR 充分利用存在一定丢包率的网络链路来降低网络延迟。
1 | echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf |
具体原理:
Keep-Alive
在TCP连接空闲的时候会关联一组计时器,当计时器倒数到0,会发送一个空的数据包进行探测保活。进行保活的操作有两个主要的目的
- 检查对方是否正常,如果对方意外关闭(例如断电),尽快关闭无用连接
- 防止因为长时间网络不活动,NAT、代理或者防火墙等断开连接。(NAT举例,长时间不连接,NAT可能不会记录具体的映射关系
这和HTTP的Keep-Alive有本质的区别。(本质上还是所在的层不同,使命不同)
应用层
常见的应用如下
FTP
- 21端口:控制连接
- 20端口:数据传输
电子邮件
- SMTP(port:25)发送邮件
- POP3(port:110)接收邮件
HTTP:非持久、无状态的连接
- GET、POST之间的区别
- 设计者本身的目的(RDF resource description framework)
- 参数
- GET 参数在URL中,明文传输、无法加密、长度受限、无法指定编码格式
- POST 参数在request body中,长度不受限,仍是明文传输
- HTTP状态码
- 200
- 300
- 400
- 500
- Cookie & Session 为HTTP引入状态
- 删除过期的Session,会用到LRU 最近最少使用。(另外还有LFU最近最不常用)
- GET、POST之间的区别
HTTPS的特点
- 特点
- 加密:非对称&对称混合加密
- 认证:数字签名(私钥加密&公钥解密)
- 完整性保护:类似MD5保证数据完整未被篡改
- SSL(官方组织) TLS(在SSL的基础上发展而来) 四次握手(索要公钥,交换对称密钥)
- 特点
DNS(域名解析)、CDN(内容分发网络)
- 单点故障
- 通信容量
- 近邻
HTTP
Keep-Alive
Keep-Alive 是一种允许多个HTTP请求使用同一个TCP连接的机制,有两个重要的相关参数
- MaxKeepAliveRequests:限制一个Keep-Alive 连接能传输的最多请求,一般会根据一个用户短时间窗口内的请求数量来决定
- KeepAliveTimeout:限制最长允许的空闲时间,通常会根据用户的访问频率来确定
KeepAliveTimeout实现的机制(在面试过程中有被问到)
- 貌似就是在连接不活跃超过配置的时间,就自动断开了(不了解具体的实现机制
这么做的好处:
保护网络资源:每个客户端使用单个连接对网络资源的负担较小
主要体现在连接数量少,服务器端需要分配的资源少
减少网络拥塞:减少服务器和客户端之间的 TCP 连接数量可以减少网络拥塞
减少延迟:减少三向握手的数量可以改善站点延迟。对于SSL/TLS 连接尤其如此 ,它需要额外的往返来加密和验证连接
HTTPS
TLS(Transport Layer Security)安全传输层协议。
CA 工作原理:
角色:A客户端,B服务器端, CA
加密流程:
- 通过CA体系,安全的交换public key
- B将public key发送给CA,CA使用自己的private key进行加密,加密之后得到一个数字证书;
- B将CA加密之后得到的证书传递给A,A使用CA发布的证书中的public key进行解密,从而获得B的public key
- 通过非对称加密算法,交换用于对称加密的密钥
- 通过对称加密算法进行正常的传输
通过上述流程确保,B在向A传递证书的过程中不会存在篡改的问题。
综合面试题
鼠标点击链接到跳转到相关页面的过程:
简单版:
- DHCP配置主机信息(如果主机最开始没有自定义IP地址)
- ARP解析MAC地址(DHCP过程只知道网关路由器的 IP 地址,还需要通过ARP获取网关路由器的 MAC 地址)
- DNS解析域名(网关路由器中已经配置了到达DNS服务器的路由表项)
- HTTP请求页面
具体而言:
DHCP配置主机信息
- 主机生成一个 DHCP 请求报文,并将这个报文放入具有目的端口 67 和源端口 68 的 UDP 报文段中,该报文段被放入在一个具有广播 IP 目的地址(255.255.255.255) 和源 IP 地址(0.0.0.0)的 IP 数据报中,该数据报被放置在目的地址 FF:FF:FF:FF:FF:FF的 MAC 帧中,并广播到与交换机连接的所有设备。
- 本地网络上的所有主机都能够收到这个广播报文,但只有DHCP服务器对此广播报文进行回答,该服务器先在数据库中查找请求主机的配置信息,若找到,返回找到的信息;否则从IP地址池中取一个地址分配给该主机,生成DHCP应答报文,其中包含IP 地址、子网掩码、默认网关路由器的 IP 地址、DNS 服务器的 IP 地址。
ARP解析MAC地址
- 主机生成一个包含目的地址为网关路由器 IP 地址的 ARP 查询报文并广播出去。
- 网关路由器接收到该帧后,发现其中的 IP 地址与其接口的 IP 地址匹配,因此就发送一个 ARP 回答报文,包含了它的 MAC 地址,发回给主机。
DNS解析域名
- 主机生成的DNS查询报文,具有目的端口52的报文段中,该报文段被放入目的地址为DNS服务器IP地址的IP数据报中,放入一个目的地址是网关路由器的MAC地址的MAC帧,发送到网关路由器。
- 网关路由器接收到包含 DNS 查询报文的以太网帧后,抽取出 IP 数据报,并根据转发表决定该 IP 数据报应该转发的路由器。(通过具有内部网关协议(RIP、OSPF)和外部网关协议(BGP)这两种路由选择协议,路由表中已经配置了网关路由器到达 DNS 服务器的路由表项)
- 该MAC帧到达DNS服务器之后,DNS抽取出 DNS 查询报文,并在 DNS 数据库中查找待解析的域名,并通过路由器反向转发回网关路由器,经过以太网交换机到达主机。
HTTP请求页面
- 经过之前的步骤获取到HTTP服务器的IP地址,先与 HTTP 服务器通过三次握手建立连接,之后生成HTTP GET报文,并交付给HTTP服务器。
- HTTP 服务器获取该报文之后,生成一个报文主体是Web页面的 HTTP 响应报文,发回给主机。
- 浏览器收到 HTTP 响应报文后,抽取渲染出 Web 页面内容,并经过四次挥手释放连接。
Linux下的网络相关
iptables
wikipedia上的结构图,iptables作用的范围主要是Network Layer上的四表5链(看不懂)
参考,四表五链
四表
- filter:过滤、防火墙,作用于INPUT ,FORWARD ,OUTPUT(进入主机、转发和进入网络)三个链
- nat:网络地址转换,作用于PREROUTING ,OUTPUT ,POSTROUTING(除了input和forward的时候)三个链
- mangle:修改报文,作用于PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING所有的链
- raw:关闭nat表上启用的链接追踪机制,作用于PREROUTING、POSTROUTING(包进入的位置上)上
五链
五链在内核五个位置放置了钩子函数
- 内核空间中:从一个网络接口进来,到另一个网络接口去的
- 数据包从内核流入用户空间的
- 数据包从用户空间流出的
- 进入/离开本机的外网接口
- 进入/离开本机的内网接口
五个链分别是
- PREROUTING:数据包进入路由之前,有raw、mangle、nat表
- INPUT:目的地址为本机,有mangle、filter表
- FORWARD:实现转发,有mangle、filter表
- OUTPUT:原地址为本机,向外发送,有filter、nat、mangle表
- POSTROUTING:发送到网卡之前,有raw、mangle、nat表
四种处理方式
- ACCEPT:允许数据包通过
- DROP:直接丢弃,不做出反馈
- REJECT:拒绝通过,必要时给出发送端反馈
- LOG:记录
结合Docker应用
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
将源地址为
172.17.0.0/16
,当不是从docker0网卡发出时,且不传到docker0网卡时,做SNAT(源地址转换,将源IP地址替换为相应网卡的地址nat :
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 5000 -j NAT --to-destination 172.17.0.4:5000
通过目的地址转换,实现外界对docker的访问
filter:
-A DOCKER ! -d 172.17.0.4/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
- 默认允许所有的外界IP访问容器
filter:
-A FORWARD -i docker0 -o docker0 -j ACCEPT
- 允许docker容器之间相互通信
小蔡支持复习
一台电脑设备支持的最多TCP连接数量
连接数量受到如下因素制约
- IP数量*端口数量=\(2^{32}\cdot2^{16}\)
- 每个socket都是一个文件,受到OS最大文件描述符的限制
- 每个socket都需要存储一些基本信息,受到OS的内存大小的限制