传输层协议主要有两个:TCP协议和UDP协议。这次主要讲解TCP协议
使用TCP协议通信的双方必须写建立连接,然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源,以管理连接的状态和连接上数据的传输。TCP连接时全双工的,即双方的数据度邪恶可以通过一个连接进行。完成数据交换后,通信双方都必须断开连接以释放系统资源。
发送端执行的写操作和接收端执行的读操作次数之间没有任何数量关系。因为缓冲区中的数据都可以一次或者多次发送和接收。
TCP头部结构
6位标志位:
UNG标志:表示紧急指针是否有效。
ACK标志:表示确认号是否有效。我们将携带ACK标志的TCP报文段为确认 报文段。
PSH标志:提示接收端应用程序应该立即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间。
RST标志:表示要求对方重新建立连接。我们将携带RST标志的TCP报文段为复位报文段。
SYN标志:表示请求建立一个连接。我们将携带SYN标志的TCP报文段为同步报文段。
FIN标志:表示通知对方本端要关闭连接了。我们将携带FIN标志的TCP报文段为结束报文段。
第一次握手:
客户端 ---> 发送SYN连接报文,序列号为x,进入SYN_SENT状态。
第二次握手:
服务器 ---> 发送SYN连接确认报文(SYN = 1,ACK = 1),序列号为y(seq = y),确认报文x(ack = x + 1),即SYN+ACK包,进入SYN_RCVD状态。
第三次握手:
客户端 --->客户端收到服务器的SYN+ACK包后,发送ACK确认报文(ACK = 1),序列号为x+1(seq = x+1),确认报文y+1(ack = y+1),进入ESTABLISHED状态。
服务器 ---> 服务器收到后进入ESTABLISHED状态。
第一次挥手:
客户端 ---> 进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
第二次挥手:
服务器 ---> 收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
客户端 ---> 收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
第三次挥手:
服务器 ---> 将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=y+1,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
第四次挥手:
客户端 ---> 收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
服务器 ---> 只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
常见问题:
1.三次握手的作用是:
1) 使得通讯双发都做好通讯的准备
2) 告诉对端本端通讯所选用的报文标识号
3) 防止已失效的连接请求报文段又突然传递到了服务端,从而产生错误
2. 三次握手那个阶段容易出现攻击?
解答: 比较典型的是 syn 泛洪攻击,或叫 syn 溢出攻击。 syn 溢出攻击,即出现在第二个阶段,如果客户机伪造出大量第一次的 sys 同步报 文,服务端就会依次耗掉很多资源来保存客户端的信息,并进行确认,实际确认是会失 败的,但失败是需要一定时间,因为服务端会连续多次进行第二次握手确认后才认定失 败。那么短时间有大量 syn 同步报文涌向服务端,服务器资源可能被耗尽,就可能导致 正常的客户端得不到响应而失败。
3.为什么是三次握手,两次可以吗?
解答: 首先,两次显然是不可以的。这类问题可以举一个反例来说明情况。 谢希仁版《计算机网络》中的例子是这样的,“已失效的连接请求报文段”的产生在 这样一种情况下:client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结 点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个 早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次 发出的一个新的连接请求。于是就向 client 发出确认报文段,同意建立连接。假设不采 用“三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有 发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源 就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况, client 不会向 server 的确认发出确认。server 由于收不到确认,就知道 client 并没有要 求建立连接。”。主要目的防止 server 端一直等待,浪费资源。 扩展下,挥手一般是四次为什么?挥手在某些情况下三次能完成吗? 某些情况下,三次是可以完成挥手的,当本端关闭了连接,恰好也同时收到了对方 的 FIN 报文,此时可以把自己的 FIN 和给对端的确认 ACK 合在一起发送。就变成了三 次。
4.三次握手那个阶段会出现异常?
解答: 第二个阶段可能异常,如果服务器相应的端口未打开,会回复 RST 复位报文,握 手失败。此外,listen 创建的监听队列达到上限,也可能失败。
5. TIME_WAIT 和 CLOSE_WAIT 有什么区别?
解答: CLOSE_WAIT 是被动关闭的一端在接收到对端关闭请求(FIN 报文段)并且将 ACK 发送出去后所处的状态,这种状态表示:收到了对端关闭的请求,但是本端还没有完成 工作,还未关闭。 TIME_WAIT 状态是主动关闭的一端在本端已经关闭的前期下,收到对端的关闭请 求(FIN 报文段)并且将 ACK 发送出去后所处的状态,这种状态表示:双方都已经完成 工作,只是为了确保迟来的数据报能被是被并丢弃,可靠的终止 TCP 连接。
6. TIME_WAIT 状态存在的意义?
解答: TIME_WAIT 状态是:主动断开连接的一端收到对端的 FIN 报文段并且将 ACK 报文 段发出后的一种状态。
意义:
1) 保证迟来的报文段能被识别并丢弃。
2) 保证可靠的终止 TCP 连接。保证对端能收到最后的一个 ACK,如果 ACK 丢失, 在TIME_WAIT状态本端还可以接受到对端重传的FIN报文段并重新发送ACK。 所以 TIME_WAIT 的存在时间为 2MSL。
7.为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
8.如果已经建立了连接,但是客户端突然出现故障了怎么办?
答:TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
9.为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。