好好搞一下这个网络,不然没法开展
docker
,netty
,nginx
等内容;
博文:从网络上浏览到的一些文章,记录在此,进行阅读吸收,如有不妥处,我会尽快处理
OSI七层参考模型
7 应用层
6 表示层
5 会话层
4 传输层
3 网络层[路由器]
2 数据链路层[交换机]
1 物理层[网卡]
TCP/IP四层模型
4 应用层
3 传输层
2 网络层
1 网络接口层
五层模型
5 应用层
4 传输层
3 网络层
2 数据链路层
1 物理层
五层模型只是OSI和TCP/IP的综合,是业界产生出来的非官方协议模型,但是很多具体的应用。实际应用还是TCP/IP的四层结构
对于每一层记录一些问题
应用层
什么是socket
关于dns
典型的分布式数据库
dns缓存
服务器端dns配置
关于p2p
以对等方式进行通信,并不区分客户端和服务端,而是平等关系进行通信。
在对等方式下,可以把每个相连的主机当成既是主机又是客户,可以互相下载对方的共享文件
传输层
连接时的状态变化:
客户端:SYN_SENT,ESTABLISHED
服务端:SYN_RECEIVED,ESTABLISHED
断开时的状态变化:
客户端:FIN_WAIT1,FIN_WAIT2,TIME_WAIT「等待2*MSL」,CLOSED
服务端:CLOSE_WAIT,LAST_ACK,CLOSED
FIN:表示己方不在发送收据了,但是还能接收数据
MSL:Maximum Segment Lifetime,报文最大生存时间
IP层中的TTL:IP 头中有一个 TTL 字段,是 IP 数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送 ICMP 报文通知源主机
TIME_WAIT 状态存在的意义:
1.经过 2MSL这个时间,足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的
2.等待足够的时间以确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭
TIME_WAIT时间过长危害:
服务端:如果服务器有处于 TIME-WAIT 状态的 TCP,则说明是由服务器方主动发起的断开请求,内存的占用
客户端:导致端口资源被占用,因为端口就65536个,被占满就会导致无法创建新的连接
如何优化 TIME_WAIT?
1.打开 net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_timestamps 选项
2.net.ipv4.tcp_max_tw_buckets,这个值默认为 18000,当系统中处于 TIME_WAIT 的连接一旦超过这个值时,系统就会将后面的 TIME_WAIT 连接状态重置,过于暴力,带来的问题也比较多,所以不推荐使用
3.在程序中设置 socket 选项,来设置调用 close 关闭连接行为:如果l_onoff为非 0, 且l_linger值为 0,那么调用close后,会立该发送一个RST标志给对端,该TCP连接将跳过四次挥手,也就跳过了TIME_WAIT状态,直接关闭
建立连接过程中服务端的两个队列:
半连接队列「SYN队列」 ,这是客户端发送SYN过来,服务器回应SYN+ACK之后,服务器当前处于SYN_RECV状态,此时的连接在半连接队列中。netstat -tnpa | grep SYN_RECV | wc -l
进行统计半连接队列长度
全连接队列「accept 队列」,客户端会返回 ACK,服务端收到第三次握手的 ACK 后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到 accept 队列,等待进程调用 accept 函数时把连接取出来。
不管是半连接队列还是全连接队列,都有最大长度限制,超过限制时,内核会直接丢弃,或返回 RST 包。
当发现 TCP 全连接队列发生溢出的时候,我们就需要增大该队列的大小,以便可以应对客户端大量的请求。
TCP 全连接队列的最大值取决于 somaxconn 和 backlog 之间的最小值,也就是 min(somaxconn, backlog)。somaxconn
是 Linux 内核的参数,默认值是 128,可以通过 /proc/sys/net/core/somaxconn
来设置其值,backlog
是 listen(int sockfd, int backlog)
函数中的 backlog 大小,Nginx 默认值是 511,可以通过修改配置文件设置其长度
防御 SYN 攻击的方法:
1.增大半连接队列,不能只单纯增大 tcp_max_syn_backlog 的值,还需一同增大 somaxconn 和 backlog,也就是增大全连接队列。否则,只单纯增大 tcp_max_syn_backlog 是无效的。增大 tcp_max_syn_backlog 和 somaxconn 的方法是修改 Linux 内核参数 2.开启 tcp_syncookies 功能的方式也很简单,修改 Linux 内核参数 3.减少 SYN+ACK 重传次数
TCP的保活机制:
定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。Linux 内核可以有对应的参数可以设置保活时间、保活探测的次数、保活探测的时间间隔,以下都为默认值:
tcp_keepalive_time=7200:表示保活时间是 7200 秒(2小时),也就 2 小时内如果没有任何连接相关的活动,则会启动保活机制
tcp_keepalive_intvl=75:表示每次检测间隔 75 秒;
tcp_keepalive_probes=9:表示检测 9 次无响应,认为对方是不可达的,从而中断本次的连接。
也就是说在 Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接。
Socket编程需要注意的是,服务端调用 accept
时,连接成功了会返回一个已完成连接的 socket,后续用来传输数据。
所以,监听的 socket 和真正用来传送数据的 socket,是两个socket,一个叫作监听 socket,一个叫作已完成连接 socket
客户端 connect 成功返回是在第二次握手,服务端 accept 成功返回是在三次握手成功之后。
客户端调用 close
,表明客户端没有数据需要发送了,则此时会向服务端发送 FIN 报文,进入 FIN_WAIT_1 状态;
TCP 协议栈会为 FIN 包插入一个文件结束符 EOF
到接收缓冲区中,应用程序可以通过 read
调用来感知这个 FIN 包;
服务端处理完数据后,自然就会读到 EOF
,于是也调用 close
关闭它的套接字,这会使得客户端会发出一个 FIN 包,之后处于
LAST_ACK 状态
为什么说TCP报文段是面向字节流的,UDP包是面向数据报的?
面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片,降低效率。若太短,会是IP太小。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。
虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。在TCP建立连接前两次握手的SYN报文中选项字段的MSS值,通信双方商定通信的最大报文长度。如果应用层交付下来的数据过大,就会对数据分段,然后发送;否则通过滑动窗口协议来控制通信双发的数据。
- tcp的几个特点
Transmission Control Protocol
分组序号
重传机制:
发送方不知道是数据分组丢失了,还是ACK丢失了,或者两个确实处理慢了,
所以采用定时器进行发送后开始计时,然后一定时间内没有收到ack,就采取适当动作,然后定时器也终止
流量控制
- 吞吐量和时延考虑
- 流量控制
拥塞控制 Congest Control
解决方案算法:
慢启动
拥塞避免
拥塞发生
快速恢复
tcp使用的是端到端的拥塞控制而不是使用网络辅助的拥塞控制,因为IP层不会向端系统提供显示的网络拥塞反馈; tcp是让每一个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率;
问题1:tcp是如何限制向其连接发送流量的? 答:
---
问题2:tcp发送方式如何感知到从它到目的地之间路径上存在拥塞呢?
答:
原则1:一个丢失的报文意味着拥塞,因此当报文丢失的时候应当降低tcp发送方的速率; 原则2:一个确认报文段指示该网络正在向接收方交付发送方的报文段,因此,当对先前未确认报文段的确认到达时,能够增加发送反送方的速率;
原则3:带宽检测,tcp调节器传输速率的策略是增加其速率以响应到达的ack,除非出现丢包事件,此时才减小传输速率
---
问题3:当tcp发送方感知到端到端的拥塞时,采用什么算法来改变其发送的速率? 答:
tcp拥塞控制算法
慢启动
拥塞避免
快速恢复
网络层
网络层的三大组件:IP协议,路由选择部分,报告数据包中的差错和某些对于网络层信息请求进行响应的设施;
广播地址: 静态路由与动态路由: DHCP ARP 路由算法
OpenVPN
NAT
Netwrok Address Translation
差错报告报文 查询报文
数据链路层
物理层
物理媒体 物理媒体包含引导型媒体和得引导型媒体; 1.引导型:电波沿着固体媒体前行.如:光缆,双铜绞线,同轴电缆; 2.非引导型:电波在空气中或外层空间中传输.如:无线局域网,数字卫星频道;
物理媒体
物理媒体包含引导型媒体和得引导型媒体; 1.引导型:电波沿着固体媒体前行.如:光缆,双铜绞线,同轴电缆; 2.非引导型:电波在空气中或外层空间中传输.如:无线局域网,数字卫星频道;
问题记录
区别: 二层交换机、三层交换机和路由器的基本工作原理和三者之间的主要区别
交换机工作原理:
当交换机收到数据时,它会检查它的目的MAC地址,然后把数据从目的主机所在的接口转发出去。 交换机之所以能实现这一功能,是因为交换机内部有一个MAC地址表,MAC地址表记录了网络中所有MAC地址与该交换机各端口的对应信息。 某一数据帧需要转发时,交换机根据该数据帧的目的MAC地址来查找MAC地址表,从而得到该地址对应的端口,即知道具有该MAC地址的设备是连接在交换机的哪个端口上,然后交换机把数据帧从该端口转发出去
二层广播,三层广播
分布式多路访问协议来协调传输和避免碰撞
1.结点处理时延 2.排队时延:流量强度 3.传输时延 指的是将所有分组的比特推向链路所需要的时间, L:该分组比特的长度, R:A,B两个路由器的链路传输速率,消耗时间:L/R 4.传播时延 和链路的物理传输介质有关系,等于两个路由器之间的距离除以传播速率
先不追究里面的细节,理解每一种协议存在的作用
掌握计算机网络领域知识的过程就是理解网络协议的构成、原理和工作方式的过程。
问题点:
一个协议定义了两个或多个通信实体之间交换的报文格式和次序,以及报文发送,接收一条报文或其他事件所采取的的动作
打算从linux中的网络相关命令开始进入,然后进行拓展开来,我们直接从
ip
命令开始
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:98:9b:e0 brd ff:ff:ff:ff:ff:ff
说明:
'2':index顺序;
'eth0':网卡接口代号;
'mtu':最大传输单元;
'qdisc':接口使用的排队规则, 'pfifo_fast'表示先进先出,'noqueue'表示接口不排队任何内容,'noop'表示接口处于黑洞模式,其会立即丢弃送达的所有数据包';
'BROADCAST':支持广播;
'MULTICAST':支持组播;
'LOWER_UP':代表链路层已经准备就绪,就是连上了网线;
'qlen 1000':队列长度;
'link/ether 52:54:00:98:9b:e0':mac地址;
'brd ff:ff:ff:ff:ff:ff':广播地址;
ecs➜ ~ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:98:9b:e0 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.17/20 brd 172.17.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe98:9be0/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:a5:b6:4c:32 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global docker0
valid_lft forever preferred_lft forever
➜ ~ ip route show | column -t
default via 172.16.8.1 dev en1
10.10.100.0/25 via 10.10.100.80 dev utun2
10.10.100.80/32 via 10.10.100.80 dev utun2
106.14.123.143/32 via 172.16.8.1 dev en1
127.0.0.0/8 via 127.0.0.1 dev lo0
127.0.0.1/32 via 127.0.0.1 dev lo0
169.254.0.0/16 dev en1 scope link
172.16.8.0/24 dev en1 scope link
172.16.8.1/32 dev en1 scope link
172.16.8.99/32 dev en1 scope link
192.168.4.0/24 via 10.10.100.80 dev utun2
192.168.5.0/24 via 10.10.100.80 dev utun2
224.0.0.0/4 dev en1 scope link
255.255.255.255/32 dev en1 scope link
对于到达 106.14.123.143 这个网络,通过网关 172.16.8.1 网关路由去进行访问
当目标主机的 IP 地址或网络不在路由表中时,数据包就被发送到默认路由(默认网关)上
route 路由表
网络命令使用
抓包工具的使用
网络设备和虚拟网络设备
Linux 虚拟网络的背后都是由一个个的虚拟设备构成的。虚拟化技术没出现之前,计算机网络系统都只包含物理的网卡设备,通过网卡适配器,线缆介质,连接外部网络,构成庞大的 Internet。随着虚拟化技术的出现,网络也随之被虚拟化,相较于单一的物理网络,虚拟网络变得非常复杂,在一个主机系统里面,需要实现诸如交换、路由、隧道、隔离、聚合等多种网络功能。而实现这些功能的基本元素就是虚拟的网络设备,比如 tap、tun 和 veth-pair。
tap/tun 提供了一台主机内用户空间的数据传输机制。它虚拟了一套网络接口,这套接口和物理的接口无任何区别,可以配置 IP,可以路由流量,不同的是,它的流量只在主机内流通。tap/tun 有些许的不同,tun 只操作三层的 IP 包,而 tap 操作二层的以太网帧。
veth-pair 是成对出现的一种虚拟网络设备,一端连接着协议栈,一端连接着彼此,数据从一端出,从另一端进。
隧道和NAT的区别
隧道是对初始报文作另一层封装,根据隧道的不同类型加相应的报文头;而NAT-PT是对报文的网络层内容进行整改,剥离原先的报文头,替换为转换后的报文头
参考:https://juejin.im/post/6844903824390537230
缓存处理:在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略
带宽优化及网络连接的使用:HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。 错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
Host头处理:在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)
长连接:HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
并行交错地发送多个请求,请求之间互不影响。
并行交错地发送多个响应,响应之间互不干扰。
使用一个连接并行发送多个请求和响应。
所有通信都在一个 TCP 连接上完成,此连接可以承载任意数量的双向数据流。
header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
HTTP2.0 使用 HPACK 压缩格式压缩请求和响应标头元数据,这种格式采用两种简单但是强大的技术:
这种格式支持通过静态 Huffman 代码对传输的标头字段进行编码,从而减小了各个传输的大小。
这种格式要求客户端和服务器同时维护和更新一个包含之前见过的标头字段的索引列表(换句话说,它可以建立一个共享的压缩上下文),此列表随后会用作参考,对之前传输的值进行有效编码。
服务端推送(server push),HTTP2.0具有server push功能。
> 可在下面留言(需要有 GitHub 账号)