I/O-计算机网络

by shihang.mai

1. OSI参考模型

网络7层协议就是OSI参考模型实现


网络7层协议

应用层: HTTP、FTP
表示层: 加密、ASCII
会话层: RPC、SQL
传输层: TCP、UDP
网络层: IP
链路层: ATM、ARP
物理层: 802.3

2. TCP/IP参考模型

TCP/IP:传输控制/网际协议


TCP_IP网络

3. TCP3次握手

目的:确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备

其实要理解TCP握手和挥手,从报文头理解最好不过


TCP报文首部.png
  • 16位端口号: 源端口号,目标端口号
  • 32位序号: 一次TCP通信(从TCP连接建立到断开)过程中某一个传输方向上的字节流的每个字节的编号
  • 32位确认号:用作对另一方发送的tcp报文段的响应。其值是收到的TCP报文段的序号值加1
  • 4位头部长度:表示tcp头部有多少个32bit字(4字节)。因为4位最大能标识15,所以TCP头部最长是60字节
  • 6位标志位:URG(紧急指针是否有效),ACK(表示确认号是否有效),PSH(缓冲区尚未填满),RST(表示要求对方重新建立连接),SYN(建立连接消息标志接),FIN(表示告知对方本端要关闭连接了)
  • 16位窗口大小:是TCP流量控制的一个手段。这里说的窗口,指的是接收通告窗口。它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度
  • 16位校验和:由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏。注意,这个校验不仅包括TCP头部,也包括数据部分。这也是TCP可靠传输的一个重要保障
  • 16位紧急指针:一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移。TCP的紧急指针是发送端向接收端发送紧急数据的方法
TCP3次握手.png

开始时,Client为Closed状态,Server端为Listen状态

  1. 第一次握手
  • Client状态变为SYNC_SEND
  • 报文头SYN = 1(SYN=1的报文段不能携带数据,但要消耗掉一个序号)
  • 32位序列号seq = x
  1. 第二次握手
  • Server状态变为SYN_REVD
  • 报文头SYN = 1
  • 报文头ACK = 1
  • 32位序号seq = y
  • 32位确认号=x+1
  1. 第三次握手
  • Client和Server状态变为ESTABLISHED
  • 报文头ACK = 1(ACK报文段可以携带数据,不携带数据则不消耗序号)
  • 32位确认号= y+1
  • 32位序列号seq = x+1

4. 3次握手原因

双方均知道自己的发收能力可行。3次已经足够了,4次显然多余

5. 4次挥手

开始时,双方都是ESTABLISHED状态


TCP4次挥手.png
  1. 第一次挥手
  • Client进入FIN_WAIT_1状态
  • 报文头FLN = 1
  • 32位序号seq = u
  1. 第二次挥手
  • Server端进入CLOSE_WAIT状态、CLIENT进入FLN_WAIT_2状态
  • 报文头ACK = 1
  • 32位确认号=u+1
  • 32位序号seq = v
  1. 第三次挥手
  • Server端进入LAST_ACK状态
  • 报文头FLN = 1
  • 报文头ACK = 1
  • 32位确认号seq = w
  • 32位确认号=u+1
  1. 第四次挥手
  • Client经历TIME_WAIT->CLOSED,Server进入CLOSED状态
  • Client从TIME_WAIT->CLOSED,需要等待2MSL(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)时间
  • 报文头ACK = 1
  • 32位序号seq = u+1
  • 32位确认号=w+1

6. 4次挥手原因

双方均知道对方已经知道自己要断开链接

7. 客户端从TIME_WAIT->CLOSED需要经历2MSL原因

TIME_WAIT状态存在的意义,下面MSL指最大报文生存时间

  • 保证可靠地终止TCP连接:处于TIME_WAIT状态的客户端会向服务端发送ACK,如果此时ACK丢失,目的端会超时重传FIN报文段,目的端收到重传的报文段最少需要2MSL,所以发送端会等待2MSL时间;
  • 客户端在发送ACK后,再等待2MSL时间,可以使本次连接所产生的数据段从网络中消失,从而保证关闭连接后不会有还在网络中滞留的数据段去骚扰服务端

此处,假如主动关闭方为Client(可以为Server主动关闭)

  • 其中1个MSL,Client发出的最后一次的ACK报文能最终到达Server
  • 另外1个MSL,保证Server,当没收到ACK,Server进行FLN重传能够到达Client

8. TCP、UDP、HTTP

  1. TCP面向连接((如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。
  2. TCP要求安全性,提供可靠的服务,通过TCP连接传送的数据,不丢失、不重复、安全可靠。而UDP尽最大努力交付,即不保证可靠交付。
  3. TCP是点对点连接的,UDP一对一,一对多,多对多都可以
  4. TCP传输效率相对较低,而UDP传输效率高,它适用于对高速传输和实时性有较高的通信或广播通信。
  5. TCP适合用于网页,邮件等;UDP适合用于视频,语音广播等
  6. TCP面向字节流,UDP面向报文

9. TCP可靠原因

  1. TCP的连接是基于三次握手,而断开则是四次挥手。确保连接和断开的可靠性
  2. TCP的可靠性,还体现在有状态;TCP会记录哪些数据发送了,哪些数据被接受了,哪些没有被接受,并且保证数据包按序到达,保证数据传输不出差错
  3. TCP的可靠性,还体现在可控制。它有报文校验、ACK应答、超时重传(发送方)、失序数据重传(接收方)、丢弃重复数据、流量控制(滑动窗口)和拥塞控制等机制

10. TCP重传机制

  • 超时重传
    在发送数据报文时,设定一个定时器,每间隔一段时间,没有收到对方的ACK确认应答报文,就会重发该报文
    这个时间RTO (Retransmission Timeou)略大于RTT(一个数据包从发出去到回来的时间)
  • 快速重传
    它不以时间驱动,而是以数据驱动。它基于接收端的反馈信息来引发重传
  • 带选择确认的重传(SACK)
    在快速重传的基础上,接收端返回最近收到的报文段的序列号范围
    SACK标记是加在TCP头部选项字段里面的
  • D-SACK
    在SACK的基础上做了一些扩展,主要用来告诉发送方,有哪些数据包自己重复接受了

11. 滑动窗口

  • 滑动窗口出现的原因:反证法,TCP 发送一个数据,需要收到确认应答,才会发送下一个数据。这样有个缺点,就是效率会比较低
  • 窗口是操作系统开辟的一个缓存空间。窗口大小值表示无需等待确认应答,而可以继续发送数据的最大值
  • TCP头部中有一个16位窗口大小字段,它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度,从而达到流量控制的目的(接受方每次收到数据包,在发送确认报文的时候,同时告诉发送方,自己的缓存区还有多少空余空间)

发送窗口


滑动窗口-发送窗口.png

接收窗口


滑动窗口-接收窗口.png

12. TCP的流量控制

就是基于上面的滑动窗口,每次服务端收到报文后,都告知客户端可用的窗口大小

13. TCP的拥塞控制

  • 拥塞窗口是由发送方维护的,它是用来估算在一段时间内这条链路可以承载和运输的数据的数量。它大小代表着网络的拥塞程度,并且是动态变化的
  • TCP的流量控制,是作用于接受者的,根据接受者的能力控制发送速度。拥塞控制,是作用在网络上的,防止过多的数据包注入到网络,避免出现网络负载过大的情况

拥塞控制用以下几种算法去控制

  • 慢启动
  • 拥塞避免
  • 拥塞发生
  • 快速恢复

13.1 慢启动

  • TCP连接完成,初始化cwnd = 1,表明可以传一个MSS单位大小的数据。
  • 每当收到一个ACK,cwnd就加一;
  • 每当过了一个RTT,cwnd就增加一倍; 呈指数让升
  • 为了防止cwnd增长过大引起网络拥塞,还需设置一个慢启动阀值ssthresh,默认65535字节(slow start threshold)状态变量。当cwnd到达该阀值后,就好像水管被关小了水龙头一样,减少拥塞状态。即当cwnd >ssthresh时,进入了拥塞避免算法

13.2 拥塞避免

  • cwnd到达慢启动阀值后
  • 每收到一个ACK时,cwnd = cwnd + 1/cwnd
  • 当每过一个RTT时,cwnd = cwnd + 1


    拥塞避免.jpg

13.3 拥塞发生

当网络拥塞发生丢包时,会发生之前提到的重试机制

  • RTO超时重传
  • 快速重传

如果发生RTO超时重传,就会使用拥塞发生算法(一夜回到解放前)

  • 慢启动阀值sshthresh = cwnd /2
  • cwnd 重置为 1
  • 进入新的慢启动过


    RTO拥塞发生.jpg

当发生快速重传时,就不需要依赖RTO超时重传

  • 拥塞窗口大小 cwnd = cwnd/2
  • 慢启动阀值 ssthresh = cwnd
  • 进入快速恢复算法

13.4 快速恢复

  • cwnd = sshthresh + 3
  • 重传重复的那几个ACK(即丢失的那几个数据包),如果再收到重复的 ACK,那么 cwnd = cwnd +1
  • 如果收到新数据的 ACK 后, cwnd = sshthresh。因为收到新数据的 ACK,表明恢复过程已经结束,可以再次进入了拥塞避免的算法了


    快速恢复.jpg

14. 半链接

  • 3次握手前,服务端会从CLOSED->LISTEN状态,同时会在内部创建半连接队列(SYN队)列和全连接队列(ACCEPT队列)
  • 3次握手服务端从LISTEN->SYN_RCVD状态,此时这个连接被推入了SYN队列(半连接队列)
  • 3次握手完后后,连接会等待被具体应用取走,被取走前,被推入到ACCEPT队列

14.1 SYN Flood攻击

它一种典型的DoS 攻击,它在短时间内,伪造不存在的IP地址,向服务器大量发起SYN报文。当服务器回复SYN+ACK报文后,不会收到ACK回应报文,导致服务器上建立大量的半连接半连接队列满了,这就无法处理正常的TCP请求。

检测方法:

netstat -n -p TCP | grep SYN_RECV

在服务器上看到大量的半连接状态时,特别是源IP地址是随机的

解决方式:

  • syn cookie:在收到SYN包后,服务器根据一定的方法,以数据包的源地址、端口等信息为参数计算出一个cookie值作为自己的SYNACK包的序列号,回复SYN+ACK后,服务器并不立即分配资源进行处理,等收到发送方的ACK包后,重新根据数据包的源地址、端口计算该包中的确认序列号是否正确,如果正确则建立连接,否则丢弃该包
  • SYN Proxy防火墙:服务器防火墙会对收到的每一个SYN报文进行代理和回应,并保持半连接。等发送方将ACK包返回后,再重新构造SYN包发到服务器,建立真正的TCP连接

15. 半关闭

当服务端处在CLOSE_WAIT时,就是所谓的半关闭状态。此时客户端可以接收服务器发送的数据,但是客户端已经不能再向服务器发送数据

大量CLOSE_WAIT的危害:如果Server大量连接长期保持在CLOSE_WAIT状态,也就是说分配的文件描述符并没有关闭并归还,可能到最后就没有可分配的文件描述符了,那么就会使一些客户端无法连接

16. Nagle算法和延迟确认

Nagle算法用来解决发送端疯狂发送很小的包问题,为了尽可能发送大块数据。它基本定义:任意时刻,最多只能有一个未被确认的小段(小于MSS的数据块)
规则如下:

  • 如果包长度达到MSS,则允许发送;
  • 如果该包含有FIN,则允许发送;
  • 设置了TCP_NODELAY选项,则允许发送;
  • 未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送;
  • 上述条件都未满足,但发生了超时(一般为200ms),则立即发送

延迟确认就是指接收方收到数据包后,如果暂时没有数据要发给对端,它可以等一段时再确认。如果这段时间刚好有数据要传给对端,ACK就随着数据传输,而不需要单独发送一次ACK。如果超过时间还没有数据要发送,也发送ACK,避免对端以为丢包。

一般情况下为了性能,这两者是不能一起使用的

17. TCP的粘包和拆包

TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题

为什么会产生粘包和拆包呢?

  • 要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包;
  • 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包;
  • 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包;
  • 待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。即TCP报文长度-TCP头部长度>MSS。

解决方案

  • 发送端将每个数据包封装为固定长度
  • 在数据尾部增加特殊字符进行分割
  • 将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段声明内容体的大小

18. 数据包发送

数据包发送
  1. 当计算机1开机时,它会在链路层发出arp协议,如图绿色。在交换机处做广播操作,发给计算机2和路由器

  2. 计算机2识别目标ip不是自己,直接丢弃。路由器识别包,然后还是用arp协议如图黄色。返回给计算机1

  3. 做完1,2步操作,那么计算机1的就有一个gateway->mac地址。

  4. 当计算机1应用层发出http请求,那么会在传输控制层进行3次握手,进行3次握手时也要发包操作

  5. 向目标ip:192.168.3.4,端口80申请握手,先用192.168.3.4&mask计算出的值与des对比,如果相同就用当前条目的gw,例子中匹配了gateway=192.168.1.1,然后这个gateway对应了一个mac地址,那么包装形如

    {
    "mac":"xxxxx",
    "ip":"xxxx",
    "port":"xxxxx"
    }
    

    向外发送

  6. mac地址解决节点的跳跃问题,而ip可以找出下一跳的地址,port找到最终处理的程序。

最后

该文章多处参考【捡田螺的小男孩】,特别鸣谢。

你可能感兴趣的:(I/O-计算机网络)