TCP相关基础知识

TCP的特点及首部格式

TCP是一种面向连接的、可靠的协议。
是TCP/IP体系中非常复杂的协议,也是非常重要的协议。
它的特点:
1)、TCP是面向连接的运输层协议。
2)、每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的。
3)、TCP提供可靠交付的服务。
4)、TCP提供双全工通信。
5)、面向字节流。

TCP报文段的首部格式:
这里写图片描述
(1)源端口和目的端口:各占两个字节,分别写入源端口号和目的端口号
(2)序号:4个字节,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号
(3)确认序号:4个字节,期望收到对方下一个报文段的第一个数据字节的序号
(4)首部长度:占4位
(5)保留:占6位,保留今后用
(6)URG(紧急URG):当URG= 1时,表明紧急指针有效
(7)ACK(确认ACK):仅当ACK= 1时确认号字段才有效
(8)PSH(推送PSH):接收方TCP收到PSH= 1的报文段,就尽快地交付接收应用进程
(9)RST(复位RST):当RST = 1时,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立运输连接。
(10)SYN(同步SYN):在建立连接时用来同步信号。
(11)FIN(终止FIN):用来释放连接
(12)窗口:占2字节,发送本报文段的一方的接收窗口
(13)检验和:占2字节,检验首部和数据这两个部分
(14)紧急指针:占2字节,指出本报文段中紧急数据的字节数
(15)选项:长度可变,最长为40字节。没有选项时,TCP的首都长为20字节。有选项时TCP的首部长度为20加选项的长度。

端口分类

1、有效端口:

IP地址的端口可以有65536(即:2^16)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(2^16-1)。
本地操作系统会给那些有需求的进程分配协议端口,每个协议端口由一个正整数标识,如:80,139,445,等等。当目的主机接收到数据包后,将根据报文首部的目的端口号,把数据发送到相应端口,而与此端口相对应的那个进程将会领取数据并等待下一组数据的到来。

2、端口的分类:
运输层的端口号分为两大类:
第一种服务器端使用的端口号(数值:0-49151)
这种端口号又分为两类:
(1)、熟知端口号(系统端口号)
数值:0-1023
这些数值可在网址www.iana.org查到。IANA把这些端口号指派给了TCP/IP最重要的一些应用程序,让所有的用户都知道。当一种新的应用程序出现后,INAN必须为它指派一个熟知端口,否则因特网上的其他进程就无法和它进行通讯。
(2)、登记端口号
数值:1024-49151
这类端口号是为没有熟知端口号的应用进程使用的。使用这类端口号必须在IANA按照规定的手续登记,以防止重复。

第二种客户端使用的端口号(短暂端口号)(数值49152-65535)
这类端口号是留给客户进程选择暂时使用。当服务器进程收到客户进程的报文时,就知道了客户进程所使用的端口号,因而可以把数据发送给客户进程。通讯结束后,刚才已使用过的客户端口号不复存在,这个端口号就可以供其他客户进程使用。

3、网络服务中常用的端口号:

1)端口:8080
8080端口同80端口,是被用于WWW代理服务的,可以实现网页浏览,经常在访问某个网站或使用代理服务器的时候,会加上“:8080”端口号。
2)端口:21
FTP服务器所开放的端口,用于上传、下载。
3)端口:22
服务:Ssh
4)端口:23
服务:Telnet,远程登录
5)端口:25
SMTP服务器所开放的端口,用于发送邮件
6)端口:80
服务:HTTP,用于网页浏览
7)端口:53
DNS:域名解析服务
8)端口:161
SNMP:简单网络管理协议


URG与PSH

URG和PSH都是TCP首部中的字段。

1、紧急URG

当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序来传送。
例如:已经发送了很长的一个程序要在远地的主机上运行。后来发现了一些问题,需要取消该程序的运行。因此用户从键盘发出中断命令(Ctrl+C)。如果不使用紧急数据,那么这两个字符将存储在接收TCP的缓存末尾。只有在所有的数据处理完毕后这两个字符才被交付接收方的应用进程。这样做就浪费了很多时间。
当URG置1时,发送应用进程就告诉发送方的TCP有紧急数据要传送。于是发送方TCP就把紧急数据插入到本报文段数据的最前面,而紧急数据后面的数据仍是普通数据。这时要与首部中紧急指针字段配合使用。

2、推送PSH

当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送PSH操作。这时,发送方TCP把PSH置1,并立即创建一个报文段发送出去。接收方TCP收到PSH= 1的报文段,就尽快地交付接收应用进程,而不等到整个缓存都填满了后再进行向上交付。

3、区别

URG交付给进程的数据:只有紧急数据
PSH交付给进程的数据:缓冲区排好序的数据及当前报文中的数据
两者的共同点:都是一种对数据的处理方式.只不过URG是处理在前端(收到数据后立马对真正意义上”数据”进行操作,所以说”紧急)。而PSH是在处理的后端,告诉内核,不用等待”满了”再递交数据递交到上层。


网络中与TCP相关的定时器

TCP在建立连接之后可能会启动四个定时器。

重传定时器

作用:保证可靠性传输
解决:每发送一个报文段就会启动重传定时器,如果在定时器时间到后还没收到对该报文段的确认,就重传该报文段,并将重传定时器复位。如果在定时器时间内收到确认则撤销该报文段的重传定时器。

坚持定时器

作用:主要用来解决零窗口大小通知可能导致的死锁问题。
死锁问题:如果接收端在向发送端发送了零窗口报文段后不久,接收端的接收缓存有了一定的存储空间,则向发送端发送一个非零窗口大小的报文段,然而这个报文段在传送过程中丢失了,发送端没有收到该报文段,就一直等待接收端发送非零窗口的报文通知,而接收端并不知道报文段丢失,而是一直等待发送端发送数据,这样就会发生死锁问题。
**解决:**TCP为每一个连接设置一个坚持定时器(持续计数器)只要TCP连接的一方收到对方的零窗口报文段,就启动坚持定时器。若坚持定时器设置的时间到期,就发送一个零窗口控测报文段。会有以下3种情况
1)对方收到探测报文段后,给出确认(现窗口值)如果窗口仍为零,则收到这个报文段的一方将坚持定时器值加倍并重启。(坚持定时器最大为60s)
2)对方接收到探测报文后,给出确认,此时窗口不为零,则跳出死锁
3)该探测报文发出后,会同时启动 重传定时器,如果重传定时器时间超时,还没收到响应,则重传探测报文。

保活定时器

作用:应对TCP连接期间,客户端和服务端长时间无数据传输的情况。
问题:当建立TCP连接后,若客户端发生故障,则服务器不能再接收客户端发送的数据,而服务端不能永久的等待下去,则需要保活定时器来解决。
原理:服务端没收一次客户端的数据,就重新设置保活定时器,通常为2小时,如果2小时没有收到客户端的数据,服务端就发送一个探测报文,以后没间隔76秒发送一次,连续发送10次探测报文后仍没有收到客户端的相应,服务器就认为客户端出现故障,终止连接。

2MSL定时器 ——- 2

MSL定时器用来计算一个连接处于Time_wait状态的时间,通常为2MSL(报文段寿命的两倍)。
作用:在TCP释放连接时,确认发送的最后一个ACK报文能够到达对方,并防止之前与本连接有关的由于延迟等原因而导致已失效的报文被误判为有效。


TCP的握手

三次握手

TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答
SYN+ACK ,并最终对对方的 SYN 执行 ACK 确认。这种建立连接的方法可以防止产生错误的连接,TCP使用的流量控制协议是可变大小的滑动窗口协议。

TCP三次握手的过程如下:
(1)客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
(2)服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
(3)客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。
那为什么要进行三次握手?
为了应对网络中存在的延迟的重复数组的问题

假设client发起连接的连接请求报文段在网络中没有丢失,而是在某个网络节点长时间滞留了,导致延迟到达server。本来这是一个已经失效的连接报文,但是server接收到这个连接报文之后,误认为client发起了新的连接,于是向client发送确认报文段。此时因为没有了连接的3次握手,client不会对server的确认报文作出回应,也不会向server发送数据,server就以为连接已经建立,一直在空等client的数据,这样server的这一部分网络资源就被浪费了。

四次挥手

建立一个连接需要三次握手,而终止一个连接要经过四次握手,这是由TCP的半关闭造成的。
(1) 某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。
(2) 接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。
注意:FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为,FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。
(3) 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。
(4) 接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。
既然每个方向都需要一个FIN和一个ACK,因此通常需要4个分节。
为什么要进行四次挥手?

因为TCP连接是全双工的网络协议,允许同时通信的双方同时进行数据的收发,同样也允许收发两个方向的连接被独立关闭,以避免client数据发送完毕,向server发送FIN关闭连接,而server还有发送到client的数据没有发送完毕的情况。所以关闭TCP连接需要进行四次握手,每次关闭一个方向上的连接需要FIN和ACK两次握手。

TIME_WAIT状态

在TCP连接中,当被动关闭连接的一方发送的FIN报文到达时,被动关闭连接的一方会发送ACK确认报文,并且进入TIME_WAIT状态,并且等待2MSL时间段。
那主动断开链接的一方为什么要进入TIME_WAIT状态 ?

这么做有下述两个原因: 1.被动关闭连接的一方在一段时间内没有收到对方的ACK确认数据包,会重新发送FIN数据包,因而主动关闭连接的一方需要停留在等待状态以处理对方重新发送的FIN数据包。否则他会回应一个RST数据包给被动关闭连接的一方,使得对方莫名其妙。 2.在TIME_WAIT状态下,不允许应用程序在当前ip和端口上和之前通信的client(这个client的ip和端口号不变)建立一个新的连接。这样就能避免新的连接收到之前的ip和端口一致的连接残存在网络中的数据包。这也是TIME_WAIT状态的等待时间被设置为2MSL的原因,以确保网络上当前连接两个方向上尚未接收的TCP报文已经全部消失。