天天看点

终于可以把TCP讲清楚了知识回顾TCP详解

文章目录

  • 知识回顾
  • TCP详解
    • 1.1 TCP数据包结构详解
    • 1.2 TCP三次握手
    • 1.3 TCP四次断开
    • 1.4 TCP定时器
    • 1.5 TCP与UDP的区别
    • 1.6 协议栈的攻击
终于可以把TCP讲清楚了知识回顾TCP详解

知识回顾

OSI七层模型 TCP/IP协议栈

终于可以把TCP讲清楚了知识回顾TCP详解

应用程(数据 data):通过人机交互提供各种各样的服务

表示层(数据 data):为上层用户解决用户信息语法问题 编码 解码 加密(即时数据) 解密

会话层(数据 data):发现 建立 维持 终止 会话进程 建立虚拟的端到端的链接

传输层(数据段 segment): 1.数据分段 2.使用端口号区分不同的服务 3.可靠传输

网络层(数据包 packet): 1.使用IP地址进行逻辑寻址 2.建立两个节点间的连接

数据链路层(数据帧 frame):

1.MAC 媒介访问控制层

​ 通过MAC地址进行物理寻址

2.LLC 逻辑链路层

​ 为上层提供FCS校验

​ 数据分帧

物理层(比特流 bit):定义电气、电压、接口规范,光学特性

总结:

上三层为应用程序对数据进行加工和处理——数据流层

下四层为数据传输层面——传输流层

TCP详解

TCP处于OSI的第四层,即传输层

四层是传输层,作用有以下三点

1.用于区分上层不同的服务,采用端口号来区分
	0-65535 1-1024(著名端口) 1024-65535(动态端口、高端口)
	
2.提供可靠的传输机制 确认 重传 排序 流控
	三次握手
	四次断开
	
3.数据分段
	MSS 最大段长度	 1480Byte
	MTU 最大传输端元	1500Byte
	一个是在传输过程中 一个是在分割数据过程中
           
常见端口号
FTP    文件传输协议	 TCP 21
Telnet  远程登录      TCP 23
HTTP   超文本传输协议 	TCP 80 
DNS    域名解析系统    UDP/TCP 53
HTTPS  安全HTTP       TCP 443
           

1.1 TCP数据包结构详解

终于可以把TCP讲清楚了知识回顾TCP详解
终于可以把TCP讲清楚了知识回顾TCP详解

字段解释:

1.端口号:用来标识同一台计算机的不同的应用进程

​ 源端口:源端口和IP地址的作用是标识报文的返回地址

​ 目的端口:指明接收方计算机上的应用程序接口

TCP报头中的源端口号和目的端口号同IP数据报中的源IP与目的IP唯一确定一条TCP连接。

2.序号和确认号seq、ackseq

​ 序号是TCP可靠传输的关键部分。序号是本报文段发送的数据组的第一个字节的序号。在TCP传送的流中,每一个字节一个序号。比如说,一个报文段的序号为300,此报文段数据部分共有100字节,则下一个报文段的序号为400。所以序号确保了TCP传输的有序性

​ 确认号是期望收到对方下一个报文的第一个数据字节的序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当ACK标志为1时才有效。

什么是ACK标志?
	TCP包头的数据结构中的第4行 URG、ACK、PSH、RST、SYN、FIN这些都是标志位,如当URG为1是,紧急指针才有效
           

3.数据偏移/首部长度

​ 由于首部可能含有可选项内容,因此TCP报头的长度是不确定的,报头不包含任何任选字段则长度为20字节,4位首部长度字段所能表示的最大值为1111,转化为10进制为15,15*32/8 = 60,故报头最大长度为60字节。首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。

4.保留

​ 为以后做打算,现在置为0

5.控制位

1)URG(urgent):紧急指针标志,为1时表示紧急指针有效,告诉系统此报文段中有紧急数据,为0则忽略紧急指针。
2)ACK(acknowledge):确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。TCP规定,在连接建立后所有报文的传输都必须把ACK置1
3)PSH(push):push标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
4)RST(reset):重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。
5)SYN (Synchronize Sequence Numbers):同步序号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。说白了就是,当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1
6)FIN(finish):finish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。
           

6.窗口

​ 滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小时一个16bit字段,因而窗口大小最大为65535

7.校验和

​ 奇偶校验,此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。

​ 注意:数据链路层,网络层、还有传输层的这种校验只是为了确认数据包的损坏与否,并没有牵扯到安全加密层面

8.紧急指针

​ 只有当控制位 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。

9.选项和填充

​ 最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。

10、数据部分

​ TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

1.2 TCP三次握手

终于可以把TCP讲清楚了知识回顾TCP详解

第一次握手:

​ 建立连接时,客户端首先向服务器发送一个SYN=1用于请求连接,seq=x的建立TCP连接的请求,并进入SYN-SENT状态

第二次握手:

​ 服务器向客户端回应一个SYN=1用于请求连接,ACK=1用于确认收到了客户端的SYN,且使ackseq有效,seq=y,ack=x+1用于期待下次收到的seq,并进入SYN-RCVD状态

第三次握手:

​ 客户端收到服务器的SYN+ACK包,并向服务器回应一个ACK=1用于确认收到了服务器发送的SYN,并回应seq为第二次握手时服务器发送的ack为x+1,在发送一个ack=y+1,即期望服务器下次发送的seq;至服务器收到这些包后,TCP的连接就建立完成了

状态详解:

​ 未连接队列

​ 在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=1)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于SYN_RECV状态(SYN-received),当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。

TIME_WAIT状态

TIME_WAIT状态存在有两个原因。

<1>可靠终止TCP连接。如果最后一个ACK报文因为网络原因被丢弃,此时server因为没有收到ACK而超时重传FIN报文,处于TIME_WAIT状态的client可以继续对FIN报文做回复,向server发送ACK报文。

<2>保证让迟来的TCP报文段有足够的时间被识别和丢弃。连接结束了,网络中的延迟报文也应该被丢弃掉,以免影响立刻建立的新连接。

追问:为什么需要三次?

TCP是可靠的传输控制协议,三次握手能保证数据可靠传输又能提高传输效率。

如果TCP的握手是两次:

<1>如果client发给server的SYN报文因为网络原因,延迟发送。由于client没有收到server对SYN的确认报文,会重发SYN报文,服务器和回复ACK,连接建立。数据发送完毕,这条连接被正常关闭。这时,延迟的SYN报文发到了server,server误以为这是client重新发送的同步报文,又回复了一个ACK,和client建立了连接。

<2>如果server给client发送的ACK报文因为网络原因,报文被丢弃,此时server认为已经建立好连接,但是client没有收到确认报文,认为没有建立好连接。client会重发SYN报文,此时server已经处于就绪状态,认为已经建立好连接。

如果TCP的握手是四次:

1.client给server发送SYN同步报文;

2.server收到SYN后,给client回复ACK确认报文;

3.server给client发送SYN同步报文;

4.client给server发送ACK确认报文。

第2.3步之间,server和client没有任何的数据交互,分开发送相当于多发了一次TCP报文段,SYN和ACK标识只是TCP报头的一个标识位。很明显,这两步可以合并,从而提高连接的速度和效率。

1.3 TCP四次断开

终于可以把TCP讲清楚了知识回顾TCP详解

为什么是三次握手?为什么不能是2、4次?

两次 导致信息不匹配

四次 把TCP会话重复发送,浪费带宽资源,没有意义

SYN,ACK种是不携带数据的,
SYN是用来同步序列号的
ACK是用来确认收到的SYN的,用于确认包的
           

为了提高连接的速度和效率。

1.4 TCP定时器

  • 建立连接定时器(connection-establishment timer)
  • 重传定时器(retransmission timer)
  • 延迟应答定时器(delayed ACK timer)
  • 坚持定时器(persist timer)
  • 保活定时器(keepalive timer)
  • FIN_WAIT_2定时器(FIN_WAIT_2 timer)
  • TIME_WAIT定时器 (TIME_WAIT timer, 也叫2MSL timer)

建立连接定时器(connection-establishment timer)

  顾名思义,这个定时器是在建立连接的时候使用的, 我们知道, TCP建立连接需要3次握手, 如下图所示:

终于可以把TCP讲清楚了知识回顾TCP详解

  建立连接的过程中,在发送SYN时, 会启动一个定时器(默认应该是3秒),如果SYN包丢失了, 那么3秒以后会重新发送SYN包的(当然还会启动一个新的定时器, 设置成6秒超时),当然也不会一直没完没了的发SYN包, 在/proc/sys/net/ipv4/tcp_syn_retries 可以设置到底要重新发送几次SYN包。

   

重传定时器(retransmission timer)

  重传定时器在TCP发送数据时设定,在计时器超时后没有收到返回的确认ACK,发送端就会重新发送队列中需要重传的报文段。使用RTO重传计时器一般有如下规则:

  1. 当TCP发送了位于发送队列最前端的报文段后就启动这个RTO计时器;
  2. 如果队列为空则停止计时器,否则重启计时器;
  3. 当计时器超时后,TCP会重传发送队列最前端的报文段;
  4. 当一个或者多个报文段被累计确认后,这个或者这些报文段会被清除出队列

  重传计时器保证了接收端能够接收到丢失的报文段,继而保证了接收端交付给接收进程的数据始终的有序完整的。因为接收端永远不会把一个失序不完整的报文段交付给接收进程。

延迟应答定时器(delayed ACK timer)

  延迟应答也被称为捎带ACK, 这个定时器是在延迟应答的时候使用的。

为什么要延迟应答呢?
  延迟应答是为了提高网络传输的效率。
           
  举例说明,比如服务端收到客户端的数据后, 不是立刻回ACK给客户端,而是等一段时间(一般最大200ms),这样如果服务端要是有数据需要发给客户端,那么这个ACK就和服务端的数据一起发给客户端了,这样比立即回给客户端一个ACK节省了一个数据包。

坚持定时器(persist timer)

  我们已经知道TCP通过让接收方指明希望从发送方接收的数据字节数(即窗口大小)来进行流量控制。如果窗口大小为 0会发生什么情况呢?这将有效地阻止发送方传送数据,直到窗口变为非0为止。接收端窗口变为非0后,就会发送一个确认ACK指明需要的报文段序号以及窗口大小。

  如果这个确认ACK丢失了,则双方就有可能因为等待对方而使连接终止:接收方等待接收数据(因为它已经向发送方通告了一个非0的窗口),而发送方在等待允许它继续发送数据的窗口更新。为防止这种死锁情况的发生,发送方使用一个坚持定时器 (persist timer)来周期性地向接收方查询,以便发现窗口是否已增大。这些从发送方发出的报文段称为窗口探查 (window probe)。

保活定时器(keepalive timer)

  在TCP连接建立的时候指定了SO_KEEPALIVE,保活定时器才会生效。如果客户端和服务端长时间没有数据交互,那么需要保活定时器来判断是否对端还活着,但是这个其实很不实用,因为默认是2小时没有数据交互才探测,时间实在是太长了。如果你真的要确认对端是否活着, 那么应该自己实现心跳包,而不是依赖于这个保活定时器。

FIN_WAIT_2定时器(FIN_WAIT_2 timer)

  主动关闭的一端调用完close以后(即发FIN给被动关闭的一端, 并且收到其对FIN的确认ACK)则进入FIN_WAIT_2状态。如果这个时候因为网络突然断掉、被动关闭的一段宕机等原因,导致主动关闭的一端不能收到被动关闭的一端发来的FIN,主动关闭的一段总不能一直傻等着,占着资源不撒手吧?这个时候就需要FIN_WAIT_2定时器出马了, 如果在该定时器超时的时候,还是没收到被动关闭一端发来的FIN,那么不好意思, 不等了, 直接释放这个链接。FIN_WAIT_2定时器的时间可以从/proc/sys/net/ipv4/tcp_fin_timeout中查看和设置。

   

TIME_WAIT定时器 (TIME_WAIT timer, 也叫2MSL timer)

  TIME_WAIT是主动关闭连接的一端最后进入的状态, 而不是直接变成CLOSED的状态, 为什么呢?第一个原因是万一被动关闭的一端在超时时间内没有收到最后一个ACK, 则会重发最后的FIN,2MSL(报文段最大生存时间)等待时间保证了重发的FIN会被主动关闭的一段收到且重新发送最后一个ACK;另外一个原因是在2MSL等待时间时,任何迟到的报文段会被接收并丢弃,防止老的TCP连接的包在新的TCP连接里面出现。不可避免的,在这个2MSL等待时间内,不会建立同样(源IP, 源端口,目的IP,目的端口)的连接。

1.5 TCP与UDP的区别

共同点:

同处于TCP/IP协议栈的传输层

不同点:

协议层面:

TCP是面向连接的可靠传输协议 协议号为6

UDP是非面向连接的不可靠传输 协议号为17

传输层面:

TCP只能一对一传输且需要维护连接状态 通过流模式传输数据

UDP支持一对一、一对多、多对一、多对多且不需要建立连接 通过数据报模式传输数据

说明:

  流模式是指存在缓存区,传进来的数据先进入缓冲区;防止发送方发送的数据太大导致接收方接受不了,而数据报追求的是速度,即即时性的将发送方发送的数据发送至接收方

数据层面:

TCP保证数据正确性、不丢包、不重复、有顺序

UDP只尽最大努力交付、不保证可靠性

适用场景:

TCP适合网络负担不大,可靠性要求高的场景

UDP适合网络负担大、响应高、客户端较多、可靠性要求不高的场景

报文层面:

封装的报文头大小不同 TCP 20byte UDP 8byte

终于可以把TCP讲清楚了知识回顾TCP详解
终于可以把TCP讲清楚了知识回顾TCP详解

1.6 协议栈的攻击

有需要的同学可以看看这个专栏,这里我做了一个导图式的总结

协议栈攻击

终于可以把TCP讲清楚了知识回顾TCP详解

继续阅读