TCP 协议

传输层协议作用

1.分段及封装应用层送来的数据
2.提供端到端的传输服务
3.在发送主机与接收主机之间构建逻辑通信
4.包括两个协议:
1)TCP
2)UDP
怎样提供的逻辑通信:
TCP 协议

两台主机进程间通信条件

本地主机(IP地址定义)
本地进程(端口定义)
远程主机(IP地址定义)
远程进程(端口定义)

端口范围

熟知端口(著名端口):0-1023,由ICANN指派
注册端口:1024-49151,IANA不指派也不控制,但须注册
动态端口(短暂端口):49152-65535,IANA不指派也不控制,无须注册

传输层的分用和复用

由应用程序产生应用进程,由应用进程产生进程端口号,由端口号提供相应的服务。
TCP 协议

运输层协议与网络层协议的主要区别

IP协议的作用范围:提供主机之间的逻辑通信
TCP和UDP 协议的作用范围:提供进程之间的逻辑通信

TCP 协议

TCP 协议是:
面向连接的:通讯双方交换数据之前必须建立连接
可靠的:多种确保可靠的机制
字节流服务:8bit(1Byte)为最小单位构成的字节流

套接字地址

TCP 使用“连接”(而不仅仅是“端口”)作为最基本的抽象,同时将TCP连接的端点称为插口(socket),或套接字、套接口。
插口和端口、IP地址的关系是:
TCP 协议

TCP发送接收过程

TCP发送进程以字节流的形式传递数据,而接收进程也把数据作为字节流来接收,类似于假想的管道
UDP发送进程发送的数据报文都是独立的,因此UDP不是面向流的协议
缓存:数据流向的每一个方向上都有两种缓存:发送缓存、接收缓存
字节号:
以字节为单位
字节号的定义范围为:0~(2^32-1)
编号机制:随机
举例:假如随机号正好是1057,而要发送6000个字节,那么字节编号范围是:1057~7056
序号:
以字节为基础,TCP给每一个报文段指派一个序号,每个报文段的序号就是在这个报文段中第一个字节数据的序号
举例:
比如TCP要传输6000个字节的文件。第一个字节的编号是10001。如果数据用5个报文段来发送,前4个报文段各携带1000字节的薮据,最后一个报文段携带2000字节的数据
报文段1>序号:10001(字节号范围:10001~11000)
报文段2->序号:11001(字节号范围:11001~12000)
报文段3->序号:12001(字节号范围:12001~13000)
报文段4一>序号:13001(字节号范围:13001~14000)
报文段5->序号:14001(字节号范围:14001~16000)
TCP 协议

在传输层向IP层发送数据时要以分组为单位,而不是按字节流来发送,TCP协议把若干字节构成一个分组,我们可以把这样的分组称为报文段( segment),这种报文段并不一定都一样长,可以几个字节,也可以是几千个字节
TCP 协议

TCP协议报文段格式

TCP 协议
源端口与目的端口:各占2字节。端口是运输层与应用层的服务接口。运输层的复用和分用功能都要通过端口才能实现。

序号字段:占4字节。TCP连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。

确认号字段:占4字节,是期望收到对方的下一个报文段的数据的第一个字节的序号。

数据偏移/首部长度:占4bit,它指出TCP首部共有多少个4字节,首部长度可以在20-60字节之间。因此,这个字段值可以在5(5x4=20)至15(15x4=60)之间,首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。

保留字段:占6bit,保留为今后使用,但目前应置为0.

紧急比特URG :当URG = 1时,表明紧急指针字段有效。它告诉系统此报文中有紧急数据,应尽快传送(相当于高优先级的数据)

确认比特ACK :只有当ACK = 1时确认号字段才有效。当ACK = 0时,确认号无效。

推送比特PSH(PuSH):接收TCP收到推送比特置1的报文段,就尽快地交付给接收应用进程,而不在等到整个缓存都填满了后再向上交付。

复位比特RST(ReSeT):当RST = 1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新新建运输连接。

同步比特SYN:同步比特SYN置为1,就表示这是一个连接请求或连接接受报文

终止比特FIN(FINaL):用来释放一个连接。当FIN = 1时,表明此报文段的发送段的数据已发送完毕,并要求释放运输连接。

端口字段:占2字节。窗口字段用来控制对方发送的数据量,单位为字节。TCP连接的一端根据
设置的缓存空间大小确定自己的接收窗口大小,然后通知对方以确定对方的发送窗口的上限。

检验和:占2字节。检验和字段检验的范围包括首部和数据这两部分。在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。

紧急指针字段:占16bit,紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。

选项字段:长度可变。TCP只规定了一种选项,即最大报文段长度MSS(Maximum Segment Size)。MSS 告诉对方TCP:“我的缓存接收的报文段的数据字段的最大长度是MSS个字节。”
MSS是TCP报文段中的数据字段的最大长度。数据字段加上TCP首部才等于整个的TCP报文段。
MSS:Maximum Segment Unit : 最大报文段长度
MTU:Maximum Transmisson Unit:最大传输单元
MSS = MTU - 20Byte(IP首部) - 20Byte(TCP首部)

填充字段:这是为了使整个首部长度是4字节的整数倍。

以下内容转载了https://blog.****.net/qq_38950316/article/details/81087809 的文章

三次握手建立TCP连接

TCP 协议

第一次握手:建立连接时,客户端发送SYN包(seq=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。(seq为序号)

第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

TCP四次挥手过程

TCP 协议第一次挥手:客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其***为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。

第二次挥手:服务器收到连接释放报文,发出确报文,ACK=1,ack=u+1,并且带上自己的***seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

第三次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的***为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的***是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

TCP 确认机制

TCP 协议

TCP窗口机制

TCP 协议

常见面试题

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】为什么不能用两次握手进行连接?

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始***进行协商,这个***在握手过程中被发送和确认。

现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的***,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。