1.TCP 协议提供的是:面向连接、可靠的、字节流服务。使用 TCP 协议通信的双方必须先建立连接,然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源,以管理连接的状态和连接上数据的传输。TCP 连接是全双工的,双方的数据可以通过一个连接进行读写。完成数据交换之后,通信双方都必须断开连接以释放系统资源。使用 tcpdump 可以抓包观察 TCP 连接的建立与关闭。该命令需要管理员权限,格式如下(假设两个测试用的主机 IP 地址为 192.168.43.214 和 192.168.43.160 )
2.三次握手发生在客户端执行 connect()的时候,该方法返回成功,则说明三次握手已经建立。三次握手示例图如下:
四次挥手发生在客户端或服务端执行 close()关闭连接的时候,示例图如下:
3.为什么是三次握手,可不可以是两次,为什么?
答案:不能是两次
①防止已过期的报文突然到达服务器,因而产生错误和资源浪费
②三次握手才能让双方都确认自己和对方的发送和接收能力都正常
③确认对方的初始序列号并告知对方自己的初始序列号
4.三次握手时可能出现什么攻击?
①SYN FLOOD攻击(SYN洪泛攻击)
SYN-FLOOD是一种常见的Dos攻击,拒绝服务攻击。通过网络服务所在的端口发送大量伪造原地址的攻击报文,发送到服务端,造成服务端上的半开连接队列被占满,从而阻止其他用户进行访问。
它的数据报特征是大量SYN包,并且缺少最后一步的ACK回复
原理:攻击者首先伪造地址,对服务器发起SYN请求,服务器回应SYN+ACK,而真实的IP会认为我没有发送请求,不做回应,而服务端没有收到回应,服务器就不知道是否发送成功,默认情况下重试5次 syn_retries,这样的话,对于服务器内存和带宽有很大的消耗
②解决SYN FLOOD方法
(1)无效连接监控
不停监视半开连接和不活动连接,当半开连接数和不活动连接数到达一定值时候,就释放系统资源。伤敌1000,自损8000
(2)延缓TCB方法
SYN FLOOD的关键是利用了,SYN数据报一到,系统就分配TCB资源。
那么我们有两种方法资源问题
Syn cache
这种技术在收到Syn时不急着分配TCB,而是先回应一个ACK报文,并在一个专用的HASH表中保存这种连接,直到收到正确的ACK,才分配TCB
Syn Cookie
用一种特殊的算法生成sequence number,算法考虑到对方的信息和己方信息,收到对方的ACK报文后,验证之后才决定是否生成TCB
5.未连接队列
在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于SYN_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入 ESTABLISHED 状态
6.SYN-ACK 重传
服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定 的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同
7.半连接存活时间
是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间
8.挥手时,可能受到什么样的攻击?
9.TCP连接各种状态解析
①FIN_WAIT_1: FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是: FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。(主动方)
②FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外一方告诉对方,我暂时还有点数据需要传送给你(ACK信息),稍后再关闭连接。(主动方)
③TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(主动方)
④CLOSING(比较少见): 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
⑤CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是查看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。(被动方)
⑥LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。(被动方)
⑦CLOSED: 表示连接中断
10.默认情况下(不改变socket选项),当你调用close( or closesocket)时,如果发送缓冲中还有数据,TCP会继续把数据发送完
11.发送了FIN只是表示本端不会继续发送数据了(应用层不会再调用send发送),但是对端还可以接收数据
12.应用层如何知道对端关闭?通常,在最简单的阻塞模型中,当你调用recv时,如果返回0,则表示对端关闭。在这个时候通常的做法就是也调用close,那么TCP层就发送FIN,继续完成四次握手。如果你不调用close,那么对端就会处于FIN_WAIT_2状态,而本端则会处于CLOSE_WAIT状态
13.在很多时候,TCP连接的断开都会由TCP层自动进行,例如你CTRL+C终止你的程序,TCP连接依然会正常关闭
14.TCP 状态转移图
TCP 连接的任意一端在任一时刻都处于某种状态,当前状态可以通过 nett stat 命令查看,下图是 TCP 连接从建立到关闭整个过程中通信两端状态的变化。其中 CLOSED 是假想的起始点,并不是一个实际的状态
上图中,TIME_WAIT 状态一般情况下是主动关闭的一端才会出现的状态。该状态出现后,会维持一段长为 2MSL(Maximum Segment Life)的时间,才能完全关闭。MSL 是 TCP 报文段在网络中的最大生存时间,标准文档 RFC1122 的建议值是 2min
15.TIME_WAIT 状态存在的原因有两点
①可靠的终止 TCP 连接
②保证让迟来的 TCP 报文有足够的时间被识别并被丢弃
在 Linux 系统上,一个 TCP 端口不能被同时打开多次(两次及以上)。当一个 TCP 连接处于 TIME_WAIT 状态时,我们将无法立即使用该连接占用着的端口来建立一个新连接。如果确实需要强制进程立即使用处于 TIME_WAIT 状态的连接所占用的端口,可以通过 setsockopt() 方法设置 socket 选项 SO_REUSEADDR 来完成
16.复位报文段
在某些特殊条件下,TCP 连接的一端会向另一端发送携带 RST 标志的报文段,即复位报文段,已通知对方关闭连接或重新建立连接。这里介绍一下三种情况:
1)当客户端程序访问一个不存在的端口时,目标主机给它发送一个复位报文段
2)异常终止连接。正常情况下,数据交换完成之后,一方给另一方发送 FIN 结束报文段。TCP 提供了异常终止一个连接的方法,即给对方发送一个复位报文段。一但发送了复位报文段,发送端所有排队等待发送的数据都将被丢弃。应用程序可以使用 socket 选项SO_LINGER 来设置发送复位报文段,以异常终止连接
3) 处理半打开连接。例如 TCP 一端关闭了连接,由于网络故障对方没有收到结束报文,对方误以为连接仍然正常。处于这种状态的连接称为半打开连接。此时如果对端向连接写入数据,则会收到本端回复的复位报文段
17.交互数据流与成块数据流
TCP 按照携带应用程序数据长度可以分为两种:交互数据和成块数据。交互数据仅包含很少的字节。使用交互数据的应用程序对实时性要求极高,比如 telnet、ssh 等。成块数据的长度则通过为 TCP 报文段允许的最大数据长度。使用成块数据的应用程序对传输效率要求高,比如 FTP
18.带外数据
有些传输层协议具有带外(out of Band,OOB)数据的概念,用于迅速通告对方本端发生的重要事件。因此,带外数据比普通数据有更高的优先级,它应该总是立即被发送,而不论发送缓冲区中是否有排队等待发送的普通数据
UDP 没有实现带外数据传输,TCP 也没有真正的带外数据。不过 TCP 利用其头部中的紧急指针标志和紧急指针两个字段,给应用程序提供了一种传输紧急数据的方式,一般只有一个字节数据
19.流式服务特点
TCP 字节流的特点,发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系,应用程序对数据的发送和接收是没有边界限制的。如下图:
20.应答确认与超时重传
TCP 发送的报文段是交给 IP 层传送的。但 IP 层只能提供尽最大努力的服务,也就是说,TCP 下面的网络所提供的是不可靠的传输。因此,TCP 必须采用适当的措施才能使两个运输层之间的通信变得可靠。TCP 的可靠传输是通过使用应答确认和超时重传来完成的
下图是通过 netstat 命令抓包看到的信息
下图是无差错时,数据交互的流程:发送端发送数据 m1 给接收端,接收端收到数据后会给发送端一个确认信息,以表明数据已经被成功收到。在发送方未收到确认信息前,M1应继续被保留,直到确认信息到达才能丢弃
下图是出现差错时,数据交互的流程:
21.滑动窗口
TCP 协议是利用滑动窗口实现流量控制的。一般来说,我们总是希望数据传输得更快一些,不会一次只发一个字节。但是如果发送方把数据发得过快,接受方就可能来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收
在 TCP 的报头中有一个字段叫做接收通告窗口,这个字段由接收端填充,是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。所以发送端就会有一个发送窗口,这个发送窗口的大小是由接收端填充的接收通告窗口的大小决定的,并且窗口的位置会随着发送端数据的发送和接收到接收端对数据的确认而不断的向右滑动,将之称为滑动窗口
发送方的滑动窗口示意图如下:
当收到 36 的 ack,并发出 46-51 的字节后,窗口滑动的示意图如下:
22.拥塞控制
在计算机网络中的链路容量(即带宽)、交换结点中的缓存和处理机等,都是网络的资源。在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫做拥塞。所谓拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制是一个全局性的过程,涉及到所有主机,所有路由器,以及与降低网络传输性能有关的所有因素
几种拥塞控制的方法:
①慢开始
②拥塞避免
③快速重传
④快速恢复
慢开始、拥塞避免、快速恢复示意图:
快速重传示意图:
23.UDP 协议特点
UDP 数据报服务特点:发送端应用程序每执行一次写操作,UDP 模块就将其封装成一个 UDP 数据报发送。接收端必须及时针对每一个 UDP 数据报执行读操作,否则就会丢包。并且,如果用户没有指定足够的应用程序缓冲区来读取 UDP 数据,则 UDP 数据将被截断