内容根据哈工大-李全龙、聂兰顺老师-计算机网络课程总结整理
建立连接,照我的理解就是通信双方互相确认了对方的存在,并且确定对方也知道自己的存在。也就是你对我的呼叫我收到了,我也知道我给你的回复你收到了。tcp里的连接,除了这些,通信双方还要为连接分配资源。比如主机A的内存中维护了一个变量connectionList,其中的每个connection,指明了双方的IP和端口号,并且分配了一块缓冲空间,用来存放收到的数据。
建立连接
tcp建立连接,采用三次握手的方式。(three way handshake,三次握手的协议其实还有其他,不止tcp)
三次握手是指三次信息交换
第一步:客户端请求建立连接。发送syn=1,seq=x
第二步:服务器同意建立连接,并为连接分配缓存。回复ack=x+1,syn=1,seq=y
第三步:客户端回复syn=0,ack=y+1
,此时可以携带正式数据
第二步完成后,服务器的资源会保留一段时间,如果超过一定时间没有收到ack,就会回收资源。
SYN洪泛攻击
上面三步的第二步完成后,服务器为连接分配了资源并会保留一段时间,客户端不再回复ack,就造成了服务器资源的浪费。如果同时用大量主机向同一台服务器发起连接请求,但是不给回复,就会造成服务器无法正常服务。这称为SYN洪泛攻击。
为什么需要三次握手?
如果一次握手,客户端发送建立连接的请求,直接就开始发送数据了,根本不管服务器是否做好了准备,甚至连接方(ip+端口)是否存在,显然不合理。
如果两次握手
第一次:客户端请求建立连接
第二次:服务器就分配资源并回复ack,连接建立
弊端1:
已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。
---《计算机网络》谢希仁版
弊端2:
从弊端1的例子知道,服务器收到连接请求后,不能知道这是一个新的连接请求,还是一个过期的历史请求,于是按正常思维,它只能认为这是一个新的,不然碰上1的错误,那不得“端口泄露”。
假如客户端发起连接请求(seq=90)
,超时,然后发起第二个(seq=100)
。
服务器经过漫长的等待,最先收到了第一个(seq=90)
,于是回复ack=91
。
此时的客户端希望的是ack=101
,知道这是一个过期的历史连接,但对不上号也就不会发数据。
(因为客户端知道这是一个历史连接,假如就用这个历史连接和服务器通信的话,如果之后seq=100
的那个请求又被服务器收到了怎么办)
弊端3:无法同步序列号
服务器不清楚自己回复的ack消息是否被收到,也就不确定客户端是否知道自己选的序列号对方是否知道。
如果该成三次握手,客户端收到ack,发现和自己希望的对不上号,于是知道这是一个过期的历史连接,于是发送RST报文段,服务器收到后释放连接。也能同步序列号。
关闭连接
客户端和服务器都能发起关闭请求,这里假设是由客户端发起
第一步:客户端请求关闭连接,发送FIN
报文段,进入FIN-WAIT-1
状态。此时客户端不会再向服务器发送数据,但还可以接收数据。
第二步:服务器回复ack,进入CLOSE-WAIT
状态。客户端收到后进入FIN-WAIT-2
状态。
第三步:服务器回复FIN
,进入LAST-ACK
状态。
第四次:客户端收到FIN
,回复ack,进入TIME-WAIT
状态。等待2MSL的时间后,客户端关闭连接,进入CLOSED
状态。服务器收到ack,也关闭连接,进入CLOSED
状态。
当服务收到FIN
时,如果没有要发送的数据,也可以直接回复ACK
+FIN
,把第二三次握手合并,这样就成了三次挥手。当成三次挥手来理解更容易:
客户端想关闭连接,负责任的做法是要告知服务器并确保对方知道,所以第一次消息就出去了。客户端对服务器,我想关闭连接
服务器收到后同意关闭,知道对方还在等自己的回复,所以就有了第二次消息。服务器对客户端,我同意关闭
,服务器也要确保自己的回复对方收到了。
客户端收到服务器同意后,立即告知对方自己收到消息了,所以就有了第三次。客户端对服务器,我收到了
,客户端然后进入等待,一段时间内如果没收到服务器的消息,就认为服务器收到消息了,然后关闭连接。