计算机网络复习------TCP的三次握手
IP协议是无连接的通信协议,它不会占用两个正在通信的计算机之间的通信线路,这样IP就降低对网络线路的需求,每条线都可以满足许多计算机之间的通信需要,通过IP,消息或者其他会被分割为较小的独立的包,并通过在因特网在计算机之间传送。IP负责将每个包,路由至其目的地。但IP协议没有做任何事情来确认数据包是否按顺序发送,或者包被破坏。所以IP数据包是不可靠的,需要由它的上层协议作出控制。
传输控制协议TCP 是传输层的协议
传输层协议TCP(Transmission Control Protocol)简介
面向连接的,可靠的,基于字节流的传输层通信协议
将应用层的数据流分割成报文段并发送给目标节点的TCP层
报文段的长度通常受该计算机连接网络的数据链路层最大传输单元及MPU的限制,之后TCP把结果包传给IP层
数据包都有序号,对方收到则发送ACK确认,未收到则重传
数据包有序号的原因就是为了保证包不丢失,***(Sequence Number),也保证了传送到目标节点包的按序处理。然后接收端实体对已成功收到的包发回一个相应的确认,即ACK确认。如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包会被认为已丢失,并且将会对其进行重传。
使用校验和未校验数据在传输过程中是否有误
TCP用奇偶校验和函数来检验数据是否有错误,在发送和接收时都要计算校验和
TCP报文头
源端口和目的端口各占两个字节
两个进程在计算机内部进行通信可以由管道,内存共享,信号量,消息队列等方法进行通信。而两个进程需要进行通信最基本的前提是能能够唯一的标识一个进程。通过唯一的标识找到这个进程。
在本地进程通信中,可以使用PID,即进程标识符,来唯一标识一个进程
但是PID只是在本地唯一,如果把两个进程放在不同的两台计算机上,如果要进行通信,PID是无法通信的。想解决这个问题,可以在传输层使用协议端口号(Protocol port number)。IP层IP地址可以唯一标识主机,而TCP协议和端口号可以唯一标识主机的一个进程。这样可以使用 IP地址 + TCP协议 + 端口号 这样的唯一标识,可以标识网络中的一个进程。这可以称为套接字(Socket)。
序号占4个字节。TCP连接中传送的字节流当中每个字节都按顺序去编号的。例如一段报文的序号字段值107,而携带的数据共有100个字段,如果有下一个报文段,其序号应该是从107+100=207开始。
确认号占4个字节。是期望收到对方下一个数据字节的序号。例如B收到从A发送过来的报文,其***字段是301,而数据全部是200字节,这表明了B正确的收到了A发送的到序号500为止的数据,301+200 - 1 = 500。因此B期望收到A下一个数据序号是501。于是B再发送给A的确认报文段中会把ACK确认号置为501。
数据偏移,由于头部有可选字段,长度不固定,因此它指出TCP报文的数据距离TCP的起始处有多元。
TCP Flags,控制位,由8个标志位来组成,每个标志位表示一个控制的功能
TCP Flags 常见的6个
URG: 紧急指针标志, 为1时 紧急指针有效, 为0时 忽略紧急指针
ACK: 确认序号标志 为1时 确认序号 有效, 为0时 表示报文中不含确认信息 忽略确认字段
PSH: push标志 为1时 代表有push的标志 指示接收方在接收到报文段以后 应尽快将报文段交给应用程序,而不是在缓冲区排队
RST: 重置连接标志 用于重置,主机崩溃或者其他原因而出现错误的连接,或者用于拒绝非法的报文端和拒绝连接请求
SYN: 同步序号,用于建立连接过程 在连接请求中SYN=1,ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1,ACK=1
FIN: finsh标志,用于释放连接 唯一标识发送方没有数据发送,即关闭本方数据流,
窗口,滑动窗口的大小,用于告知发送端接收,接收端的缓存大小,以此来控制发送端发送数据的速率,从而达到流量控制
校验和,指的是奇偶校验,是对整个的TCP报文段包括TCP头部和TCP数据以16位进行计算所得。由发送端计算和存储,并由接收端进行验证。
紧急指针:只有TCP Flags 的URG 为1 的时候才有效,指出本报文段的紧急数据的字节数
和选项填充:其长度可变,定义一些其他的可选参数
当应用程序希望通过TCP与另一个应用通信时,它会发送一个通信请求,这个请求必须被送到一个确切的地址,在双方握手之后,TCP将在两个应用之间建立一个全双通的通信,这个全双通的通信将占用两个计算机之间的通信线路,直到被一方,或者双方关闭为止。
全双通,A可以给B发送信息的同时,B也能够给A发信息。
"握手"是为了建立连接,TCP三次握手的流程图如下
ack acknowledge 通知,告知
第一次握手
一开始客户端和服务器端都处于Close状态。
刚开始的时候TCP服务器进程先创建传输控制块(PCD),时刻准备接受其他客户进程发送过来的连接请求。
此时服务端进入了Listen,即监听的状态。此时客户端进程也先创建一个传输控制块(PCD)然后向服务器发出连接请求报文,SYN就是TCP Flags 的同步序号,SYN =1,选择一个初始序号seq =x ,x可以是任意的正整数值。
此时TCP客户端进程就进入了一个SYN-SENT同步已发送的状态,发送给服务端的数据包,即报文端会被称为SYN报文段,不能携带数据,但是要消耗一个序号。
第二次握手
当服务器接收到一个报文请求之后,同意连接,则发出确认报文,确认报文中包含TCP Flags中的 SYN,ACK 两位的字段。
SYN=1,ACK=1,seq=y,ack=x+1。
ack = x+1的原因是第一次握手SYN报文中指定了seq=x,服务端要回应相关的信息,并且第一次握手中报文消耗了一个序号,因此ack = x +1,同时为自己的缓存初始化一个***,即seq=y。此时服务器就进入到了SYN-RCVD,即同步收到的状态。
这个报文也是不能携带数据的,同时也需要消耗一个序号。
第三次握手
当TCP客户进程收到确认报文之后,还要给服务器一个确认。ACK=1,seq=x+1,ack=y+1。
ack = y+1,原因是服务器给客户端发送一个seq=y,客户端作为回应。所以就加了1。同时第二次握手的报文会消耗一个序号。
同时第一次握手的时候,客户端告知(ack)服务器序号被+1了,即seq =x ,第二次握手时 ack = x +1 。所以第三次握手时候seq = x+ 1。
此时TCP连接建立,客户端就进入了ESTAB-LISHED,即已建立连接的状态,此时TCP规定这个时候的报文段可以携带数据。第一次,第二次握手的报文段都是不可以携带的。也可以不携带数据,这样就不会消耗序号了。
当服务器也收到了客户端的确认后也会进入ESTAB-LISHED状态。
完成三次握手之后,双方就可以开始通信了。
总结
在TCP/IP协议中,TCP协议提供可靠的链接服务,采用三次握手建立一个连接
第一次握手:建立连接时,客户端发送SYN包(SYN=j)到服务器,进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此时包发送完毕,客户端和服务区进入ESTABLISHED状态,完成三次握手。
为什么需要三次握手才能建立起连接?
为了初始化Sequeue Number 的初始值
通信的双方,要互相通知对方自己初始化的Sequeue Number,也就是三次握手图中的x和y,这个号要作为以后的数据通信的序号,以保证应用层接收到的数据不会因为网络上传输的问题,而乱序,即TCP会用这个序号来拼接数据,因此在服务器回发的它的Sequeue Number,即第二次握手之后,还需要发送确认报文给服务器,告知服务器说客户端已经收到你的初始化的Sequeue Number了。
首次握手的隐患 SYN超时
问题起因分析
Server收到Client的SYN,回复SYN-ACK的时候未收到ACK确认
假如Server端接收到Client端发送的SYN,回复SYN-ACK之后,Client就掉线了,此时Server端没有收到Client端发送回来的ACK包的确认,这个连接就回处于一个中间状态,即没有成功,也没有失败
Server不断重试直到超时,Linux默认等待63秒才断开连接
Server端在一定时间内没有收到Client端的回值,会重发SYN-ACK,在Linux下重试次数为5次,重试间隔时间从1s开始,每次时间间隔都会翻倍增加,比如说1s,2s,4s,8s,16s。总共是31s。在第五次发出去之后,还需要等待32s才能够判定为超时,才会断开连接。
针对SYN Flood的防护措施
如果恶意程序给服务器发出一个SYN报文,发出之后就下线,这样服务器需要默认等待63s,才会断开这个连接,这样攻击者就会把服务器的SYN连接的队列耗尽,让正常的连接请求不能被处理
当SYN队列满后,通过tcp_syncookies参数回发SYN Cookie
tcp会通过源地址端口,目标地址端口,和时间戳,打造出一个特别的Sequeue Number回发回去,简称SYN Cookie
如为正常连接则Client会回发SYN Cookie,直接将建立连接
通过SYN Cookie 即便此时SYN队列满了 本次连接请求不在队列中 依然能够建立连接进而解决了问题的发生
建立连接后,Client出现故障怎么办?
保活机制
向对方发送保活探测报文,如果未收到相应则继续发送
在保活时间(KeepAliveTime),这段时间内,连接处于非活动状态,开启保活功能的一端,将向对方发送一段保活探测报文,如果发送端没有收到响应的报文,那么经过已经提前配置的好的保活时间间隔(Keepalive Interval),将继续发送保活探测报文。
尝试次数达到保活探测数仍未收到相应则中断连接
直到发送探测报文的次数,达到保活探测数,这时对方主机将被确认为不可达,连接也将被中断。