传输层之TCP协议
传输层之TCP协议
2019年7月28日
17:32
TCP协议
传输层最重要的协议为TCP协议和UDP协议。TCP协议复杂且面向连接,但传输可靠。UDP协议简单且不面向连接,传输不可靠。
TCP比较出众的一点就是提供一个可靠的,流控的数据传输
传输层的出现有个重要的原因:端口号。
IP协议进行的是IP地址到IP地址的传输,这意味者两台计算机之间的对话。但每台计算机中需要有多个通信通道,并将多个通信通道分配给不同的进程使用。一个端口就代表了这样的一个通信通道。
网络层在逻辑上提供了端口的概念。一个IP地址可以有多个端口。一个具体的端口需要IP地址和端口号共同确定(我们记为IP:port的形式)。
双向连接:
TCP连接是双工(duplex)的。双向连接实际上就是建立两个方向的TCP传输。因此,主机与服务器的交互可能是双向的~
TCP端口号
TCP允许一个主机同时运行多个应用进程。每台主机可以拥有多个应用端口,每对端口号、源和目标IP地址的组合唯一地标识了一个会话。端口分为知名端口和动态端口。
有些网络服务会使用固定的端口,这类端口称为知名端口,端口号范围为0-1023。动态端口号范围从1024到65535
TCP 头部:
TCP通常使用IP作为网络层协议,这时TCP数据段被封装在IP数据包内。
TCP数据段由TCP Header(头部)和TCP Data(数据)组成。TCP最多可以有60个字节的头部,如果没有Options字段,正常的长度是20字节。
TCP Header是由上图标识一些字段组成,下面是对字段的介绍:
- 16位源端口号:源主机的应用程序使用的端口号。
- 16位目的端口号:目的主机的应用程序使用的端口号。每个TCP头部都包含源和目的端的端口号,这两个值加上IP头部中的源IP地址和目的IP地址可以唯一确定一个TCP连接。
- 32位序列号:用于标识从发送端发出的不同的TCP数据段的序号。数据段在网络中传输时,它们的顺序可能会发生变化;接收端依据此序列号,便可按照正确的顺序重组数据。
- 32位确认序列号:用于标识接收端确认收到的数据段。确认序列号为成功收到的数据序列号加1。
- 4位头部长度:表示头部占32bit字的数目,它能表达的TCP头部最大长度为60字节。
- 16位窗口大小:表示接收端期望通过单次确认而收到的数据的大小。由于该字段为16位,所以窗口大小的最大值为65535字节,该机制通常用来进行流量控制。
16位校验和:校验整个TCP报文段,包括TCP头部和TCP数据。该值由发送端计算和记录并由接收端进行验证。
TCP 三次握手
建立起一个TCP连接需要经过“三次握手”:
第一次握手:客户端发送请求建立连接报文(seq = x,同时SYN置1,表示第一次建立连接)到服务器,并进入SYN_SENT状态,等待服务器确认;
第二次握手:服务器收到SYN包,回复客户的请求报文(seq =y,ack=x+1),同时回包,即SYN+ACK包(SYN、ACK置1,ACK置1表示同意建立连接),此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”
之所以要三次握手的原因
第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。
客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。
TCP四次挥手:

我们可以看到,连接终结的过程中,连接双方也交换了四片信息(两个FIN和两个ACK)。TCP并没有合并FIN与ACK片段。原因是TCP连接允许单向关闭(half-close)。
假设Client端发起中断请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说“我client端要发给你了”,但是如果你还没有数据要发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,”告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息”。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。
当Server端确定数据已发送完成,则向Client端发送FIN报文,”告诉Client端,好了,我这边数据发完了,准备好关闭连接了”。Client端收到FIN报文后,”就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态。
TIME_WAIT(2s)
客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:
- 确保最后一个确认报文(回应server的ACK)能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
- 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。
(因为各种网络原因,可能会存在某些报文比较晚到,等待两秒是为了其报文的消散)
原因: 因为下一次建立的TCP可能还是那些四元组,所以会收到旧报文
已使用 Microsoft OneNote 2013 创建。
