如果要用一句话总结TCP是什么,我想应该是:TCP是因特网运输层的面向连接的、可靠的、基于字节流的、全双工的运输协议
TCP运输层协议服务
在分析TCP服务之前需要说明TCP在网络协议分层中处于哪个层次,下图是TCP/IP协议族的四个层次:
TCP和UDP都使用相同的网络层(IP),但是TCP向应用层提供了和UDP完全不同的服务,TCP提供了一种面向连接的、可靠的字节流服务。
TCP的面向连接意味着使用TCP的两个应用在交换数据之前必须建立一个TCP连接。这就类似于平时我们使用微信语音或者视频聊天时,必须先发起语音申请,等待对方接通之后,然后才能聊天。所以在TCP连接中只有两方彼此通信,我们平时说的广播和多播并不适用于TCP。
一旦建立起一个TCP连接,两个进程之间就可以互相发送数据了,这里模拟一下客户进程向服务器进程发送数据的情况,如下图:
从上图可以看出,客户端进程通过套接字(socket)传递数据流。套接字将数据传入客户端运行的TCP控制之后,TCP就会将数据引导到该链接的发送缓存中,发送缓存是在三次握手初期设置的缓存之一。当数据进入发送缓存之后,TCP就会不时的从发送缓存取出一块数据,TCP应该在它方便的时候以报文段的形式发送数据。
最大报文段长度(MSS)
最大报文段长度通常根据最初确定的由本地发送主机发送的最大链路层帧长度来设置,最大链路层帧长度即所谓的最大传输单元(Maximum Transmission Unit)。MSS=MTU-20字节TCP报头-20字节IP报头。以太网和PPP链路层协议都具有100字节的最大传输单元,因此MSS的典型值为:1500-20-20=1460字节。
TCP报文段结构
TCP报文段由首部字段和一个数据字段组成,如下图所示:
如上图所示,数据字段包含一块应用数据,就如上段内容所说,MSS限制了报文段数据字段的最大长度。当TCP发送一个大文件时,TCP通常会将文件分为MSS大小的若干块。
首部包括源端口号和目的端口号,被用于多路复用/分解来自或送到上层应用的数据,TCP首部也包括校验和字段。
UGR:紧急指针有效
ACK:确认序号有效
PSH:接收方应该尽快将这个报文段交给应用层
RST:重建连接
SYN:同步序号用来发起一个连接
FIN:发端完成发送任务
可以看到窗口大小只有16位,也就是最大窗口大小是65535个字节(64KB),TCP的流量控制就是由连接两端通过声明的窗口大小来提供。
校验和贯穿了整个TCP报文段,即TCP首部和TCP数据。校验和是一个强制性的字段,一定是由发端计算和存储,由接收端进行验证。
TCP面向连接
我们知道TCP是面向连接的协议,那么什么是长连接?什么是短连接?什么是连接?
长连接就是当实现客户端和服务端连接成功后可以连续地传输数据,这个过程中连接保持开启的状态,并且数据即使传输完毕连接也不会关闭。在socker通信中是指建立socket连接后,无论是否使用该连接,连接都保持连接的状态。
短连接就是什么时候需要传输数据就创建连接,当数据传输完毕,该连接也就不存在了。如果想再次传输数据,需要重新创建新的连接。
连接是在TCP/IP中,连接是客户端和服务端确认彼此存在的过程,要实现这个过程,就需要客户端和服务端创建连接,创建连接需要客户端和服务端进行三次握手,只有握手成功之后,双方才能进行通信。
长连接的优缺点:
优点:
我们知道长连接建立之后,客户端不需要再每次传输数据时创建连接,这样就减少了握手确认时间,提高程序效率。
缺点:
在服务器端保存了多个socket对象,大量占用服务器资源。
短连接的优缺点:
优点:
对应长连接的缺点,短连接不需要在服务器端保存多个socket对象,降低内存占用率。
缺点:
缺点也是对应长连接的优点,在每次通信时都需要创建新连接,进行三次握手增加处理时间,降低程序使用率。
三次握手
三次握手顾名思义就是通过三次数据交换建立连接,具体实现如下图所示:
通过三次握手确认的主要信息是约定好双方后续通信需要的起始***、窗口缩放大小等信息。下面对三次握手做一个简单的介绍。
-
发端通常是客户,发送一个SYN段指出客户打算连接的收端(服务器端)的端口,以及初始序列,这个SYN端为之前介绍的报文段1。
-
收端作为回应,发出包含服务器的初始化序列SYN,同时将确认序号ACK设置为客户端请求时ISN加1以对客户的SYN报文段进行确认,SYN占用一个***。
-
类似于服务器确认客户端SYN信息,客户必须将确认序号设置为服务器的ISN加1以对服务器的SYN报文段进行确认。
三次握手用我们日常生活中的例子来总结,类似于我们一次简单的发快递服务,流程如下:
-
在快递平台填写基本信息,提交给物流公司(类似于三次握手第一次握手)。
-
快递员打电话确认基本信息(类似于第二次握手)。
-
快递员上门取件,确认信息(类似于第三次握手)。
其实各种技术源于生活,服务于生活,在学习时在生活中都能找到非常多的例子,这样可以帮助记忆、理解。
TCP协议是可靠的
我们知道在网络通信中,UDP协议是不可靠的,TCP是可靠的,那么什么机制保证了TCP协议的可靠性了,具体原因如下:
-
应用数据分割。TCP在发送数据时会将应用数据分割成最合适发送的数据块,所以应用程序产生的数据长度将保持不变。
-
定时器。当TCP发出一条信息之后,就会启动一个定时器,等待目的服务器确认收到该信息。如果目的服务器在定时器范围内没有确认反馈,就会重发这条信息。
-
对每个报文段提供校验和。在前面介绍TCP报文结构时就已经解释过,校验和是一个强制性字段。这是一个端到端的校验和,目的就是为了检测数据在传输过程中的每一个变化细节。如果收到报文之后发现校验和错误,TCP就会丢弃该报文并不确认,触发TCP重发机制重发该信息。
-
重新排序机制。TCP使用的网络层是IP,IP数据报到达目的服务器可能会失序,因此会导致TCP报文的失序,所以TCP会将收到的报文重新排序之后再交给应用层。
-
丢弃机制。IP数据报可能会重发,因此TCP接收端会丢弃重复的数据报。
-
流量控制。在前面介绍过TCP的缓存空间,TCP的接收端只接受另一端发送接收缓存空间能容纳的数据大小,这样就防止了数据溢出。
通过上述所描述的机制,确保了一个进程从其接收缓存中读出的数据流是无间隔、无损坏、非冗余和按序的数据流;即该接收端接收到的字节流和发送端发出的字节流是完全相同的。
TCP字节流服务
TCP是一种字节流协议,流的定义没有固定的边界,可以是二进制数据,也可以是ASCII字符或者其他类型数据。TCP对字节流的内容不做任何解释,对字节流的解释由TCP连接双方的应用层负责。
发端和收段通过TCP连接交换字节流,TCP不在字节流中插入任何记录标识信息,这就是TCP的字节流服务。
TCP全双工服务
TCP提供的是全双工服务,即连接两端可以是这样的形式:客户端/接收端,接收端/客户端,也就是说连接通信的双方既可以接收数据,也可以发送数据。例如:一台主机上的进程A和另一台主机上的进程B存在TCP连接,那么应用层数据可以从A流向B,也可以从B流向A。
TCP提供的服务总是点对点的连接,即是单个发送方和单个接收方的连接,绝对不会存在多播的情况发生。
总结
TCP 是一个可靠的(reliable)、面向连接的(connection-oriented)、基于字节流(byte-stream)、全双工(full-duplex)的协议。
留一个思考题:对于一次电话交谈,哪一方是主动打开?哪一方是被动打开?是否允许同时打开?是否允许同时关闭?
实时博文,可以关注公众号《编程之艺术》