网络编程---TCP连接的建立(三次握手)

前几个博客一直在说TCP是面向连接的服务,那么TCP连接的建立和关闭是怎样一回事?

TCP连接的建立

起初两端的TCP进程都处于CLOSED(关闭)状态

我们从tcp编程就可以知道每次是服务器首先启动,启动之后实际上是创建了TCB传输控制块,随后进入LISTEN状态,等待客户端连接请求。客户端启动起来也是先创建TCB传输控制块,接下来连接阶段。

ps:seq是数据包本身的序列号;ack是期望对方继续发送的那个数据包的序列号。

(1)第一次握手:

Client发出连接请求报文段(SYN报文段),将标志位SYN置为1,随机产生一个初始序号seq=x(以该序列号为原点,对自己将要发送的每个字节的数据进行编号),并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。(SYN=1的报文段不能携带数据,但是要消耗掉一个序号)

(2)第二次握手:

Server收到数据包后由标志位SYN=1知道Client请求建立连接,如果同意建立连接,则向Client发送确认报文段,在确认报文段中Server将标志位SYN和ACK都置为1,确认号是ack=x+1(因为客户端发送给服务器的SYN报文段占用了1个序号),同时随机产生一个初始序号seq=y,并将该数据包发送给Client以确认连接请求(该报文段也不能携带数据,也要消耗掉一个序号),Server进入SYN_RCVD状态。

(3)第三次握手:

Client收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则还需要向Server给出确认。将标志位ACK置为1,ack=y+1,初始序号seq=x+1,并将该数据包发送给Server,Server检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。(ACK报文段可以携带数据,但是如果不携带数据则不消耗序号,下一个报文段的序号仍然是x+1

当客户端发送给服务器的确认报文段丢失了,发生什么?

这个确认报文段不会超时重传,TCP不会为没有数据的ACK进行超时重传的,准确的来说是对于这种不消耗序号的报文段是不能进行超时重传的,另外对于不消耗序号的报文段也是无需进行确认的。那么这也就解释了为什么SYN报文段没有数据但是也需要进行确认,它也可以进行超时重传。所以,当客户端发送给服务器的确认报文段丢失了,ACK不会超时重传,而是服务器重新传自己的SYN报文段,直到收到客户端发送的ACK确认报文段。如果ACK需要确认,那么就成为死循环了。

实际上可以分为三种情况:(客户端发送完ACK,单方面认为自己已连接,但是服务器并没有处于已连接状态)

<1> 假定此时双方都没有数据发送,服务器会周期性超时重传(第二次握手),直到收到客户端的确认,收到之后服务器的TCP 连接也为 Established状态,双向可以发包。

<2>假定此时A有数据发送,服务器收到客户端的 Data + ACK,自然会切换为established 状态,并接受客户端的Data。

<3>假定服务器有数据发送,数据发送不了,会一直周期性超时重传SYN + ACK,直到收到客户端的确认才可以发送数据。(与第二种情况基本相同)

两次握手不可以的原因

1:我们知道保证TCP可靠传输的一个重要机制是超时重传机制,如果没有第三次确认,服务器不知道客户端是否已经收到了它发的消息,所以它在一段时间之后会超时重传,这里会导致可能服务器发了多次之后关闭,所以需要第三次的确认。

2:防止失效的连接请求报文段被服务端接收,从而产生错误

eg:若建立连接只需两次握手,客户端并没有太大的变化,仍然需要获得服务端的应答后才进入ESTABLISHED状态,而服务端在收到连接请求后就进入ESTABLISHED状态。此时如果网络拥塞,客户端发送的连接请求迟迟到不了服务端,客户端便超时重发请求,如果服务端正确接收并确认应答,双方便开始通信,通信结束后释放连接。此时,如果那个失效的连接请求抵达了服务端,由于只有两次握手,服务端收到请求就会进入ESTABLISHED状态,以为之前的客户端又要与自己通讯,那么服务器就会等待发送数据或主动发送数据。但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,这样浪费服务端连接资源。

ps:四次握手是可以的,但是没有必要,因为我们服务器给客户端发送SYN与ACK发送方式是很相似的,没有必要将两个单独发送,可以将两个和在一起发送,就可以提高连接的效率与速率。

SYN攻击

在三次握手过程中,服务器发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接状态.此时服务器处于SYN_RCVD状态.当收到ACK后,服务器转入ESTABLISHED状态.

Syn攻击就是攻击客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的进行超时重传,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。Syn攻击是一个典型的DDOS攻击。检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击.在Linux下可以如下命令检测是否被Syn攻击

netstat -nap | grep SYN_RCVD

猜你喜欢

转载自blog.csdn.net/Eunice_fan1207/article/details/84330298