TCP 干货
前言
今天博主将为大家分享TCP系列:TCP 干货,不喜勿喷,如有异议欢迎讨论!
整理一下 TCP 的一些知识要点,作为一名开发者来说,尽管有那么多的基础设施(框架、组件)帮我们屏蔽了这些细节。当我仍然认为了解它的一些基本原理必有些裨益,尤其是当你在分布式环境上遇到一些棘手问题时,一些原理性的知识可能会让你快速找到答案,有一个强大的地基才能写出健壮的程序!
起源
TCP 是传输层的协议,全称是叫做 Transmission Control Protocol,这个协议在 IETF RFC 793 进行了定义。 在互联网产生之前,我们的电脑都是相互独立的,每台机器都有着自己的操作系统并保持着自己的运行。 于是,为了将这些电脑连接起来,并能够基于一种”通道”的形式进行数据、资源的传输及交互,IETF 制定了 TCP 协议。
那么,IETF又是什么? 这是一个令人尊敬的技术组织,叫 Internet Engineering Task Force,即互联网工程任务组。 这是一个成立于1985年的开放性组织,现在我们所提到的 HTTP、TCP、IP 这些重要的网络协议,都是出自于该组织。 可以这么说,IETF 是互联网的始作俑者,没有它就没有现在繁荣的互联网了。
值得一提的是,IETF并非权贵组织,它是一个”来自民间” 的自组织、自管理的团队,非常崇尚于自由平等的精神。
整个互联网的底层机制是由一套标准网络协议组成的,为了更方便于理解,人们便定义了所谓的“网络分层模型”。 在学习计算机网络课程的时候,都会提到两种网络模型,如下:
(在这里可以联想到LVS工作在网络四层而Nginx工作在网络七层)
-
OSI 模型,全称为 Open System Interconnection
即开放系统互联模型,这个是由 ISO(International Organization for Standardization) 国际标准化组织提出的。 它主要是用来解决当时各个网络技术供应商在协议上无法统一的问题,通过将整个网络体系结构抽象为 7层,从最底层的物理层、数据链路层一直到最上面的应用层都做了定义。 -
TCP/IP,即 TCP/IP Protocol Suite(协议套件)是一个以TCP协议和IP协议为核心的通信模型,该模型采用协议堆栈的方式来实现许多通信协议,并将通讯体系抽象为4层。 TCP/IP 模型最早发源于美国国防部(缩写为DoD)的ARPA网项目,此后就交由IETF组织来维护。
TCP/IP 基本上是OSI 模型的简化版,当然也更加容易理解。
在网络层以下,物理层、数据链路层所涉及的一些技术手段及概念都相对晦涩难懂,就比如光缆、中继器、交换机等需要一些专业背景才能掌握通透。 对于大多数的软件应用来说,将网络层以下的部分统称为“网络接口层” 无疑是更加简单的。
OSI 模型尽管非常完善且全面,但已经被 TCP/IP 模型所淘汰,在互联网应用盛行的今天很少被提及。
TCP 协议
TCP 是整个 TCP/IP 协议族中最重要的传输层协议,它定义了一种面向连接的、可靠的、基于流的传输方式。 HTTP 是基于 TCP 的,所以说 TCP 是整个互联网的协议其一并不为过。 同时,我们在使用 HTTP 协议实现应用系统间的交互时,也经常免不了会与 TCP 打上交道。因此有必要了解一些基本机制。
TCP 的特点?
-
首先,TCP 是基于连接的,也就是在进行数据传输之前,客户端与服务端(或者说是通信的双方)需要先建立一个可信的连接。 在数据传输结束后,再通过一种协定的方式断开连接,由通信的双方释放资源。这里涉及到的,就是常说的”三次握手”、“四次挥手”
-
其次,TCP 是可靠的,它定义了一种数据包的”超时重传机制”,简单说,就是每一个数据包在发送出去后的都会等待一个响应。 如果指定时间内没有收到响应,由发送方进行一定次数的重传来保证数据的可靠传输。
-
最后,TCP 是基于流的,这是指在传输数据时应用层不需要关注数据包的边界,TCP在数据传输时会自动根据网络环境将数据进行缓冲、分组、合并。 这点跟基于报文的协议(UDP)是截然不同的。当然,基于流的传输也保证了数据收发的有序性,因此每个数据包都附带上一个属于当前连接的序列号。
全双工通信
全双工是通讯上的术语,一般在软件开发领域提到的并不多。 这是指数据同时在两个方向上传输,TCP 是基于全双工的可信传输协议。 当然 UDP 也可以实现全双工的传输,但 TCP 只能实现点对点的传输,无法支持广播或者多播(分组)
半双工的区别在于,同一时间只能有一个方向的传输
TCP 的数据包如何组织?
透视一个协议的最原始的方法就是看它的数据包,一个TCP 的报文格式如下:
TCP协议如何保证传输的可靠性
-
端口号:用来标识同一台计算机的不同的应用进程。
1)源端口:源端口和IP地址的作用是标识报文的返回地址。
2)目的端口:端口指明接收方计算机上的应用程序接口。
TCP报头中的源端口号和目的端口号同IP数据报中的源IP与目的IP唯一确定一条TCP连接。 -
序号和确认号:是TCP可靠传输的关键部分。序号是本报文段发送的数据组的第一个字节的序号。在TCP传送的流中,每一个字节一个序号。e.g.一个报文段的序号为300,此报文段数据部分共有100字节,则下一个报文段的序号为400。所以序号确保了TCP传输的有序性。确认号,即ACK,指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当ACK标志为1时才有效。比如建立连接时,SYN报文的ACK标志位为0。
-
数据偏移/首部长度:4bits。由于首部可能含有可选项内容,因此TCP报头的长度是不确定的,报头不包含任何任选字段则长度为20字节,4位首部长度字段所能表示的最大值为1111,转化为10进制为15,15*32/8 = 60,故报头最大长度为60字节。首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。
-
保留:为将来定义新的用途保留,现在一般置0。
-
控制位:URG ACK PSH RST SYN FIN,共6个,每一个标志位表示一个控制功能。
1)URG:紧急指针标志,为1时表示紧急指针有效,为0则忽略紧急指针。
2)ACK:确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。
3)PSH:push标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
4)RST:重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。
5)SYN:同步序号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。
6)FIN:finish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。 -
窗口:滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小时一个16bit字段,因而窗口大小最大为65535。
-
校验和:奇偶校验,此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。
-
紧急指针:只有当 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
-
选项和填充:最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。
-
数据部分: TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。
一般情况下TCP 头部为20字节,加上20字节的 IP头部,一个数据包至少包含40字节的头部
TCP 工作流程
链是指链路,这个是物理层的概念,比如光缆光纤,或是无线的电磁波。 但这里所说的链路其实是网络连接的意思,即 IP 上层的概念。
那么,一个TCP 正常的通讯流程,会包含建链(建立连接)、传输数据、拆链(关闭连接),
-
服务器端:
socket():创建一个无连接的套接字,返回描述符
bind():绑定一个端口
listen():把套接字转换成一个监听套接字,第二个参数( backlog)的作用是指定内核允许在这个监听描述符上排队的最大客户连接数
accept(): 阻塞进程等待连接,返回一个连接套接字 -
客户端:
connect():通知内核去主动连接服务器,也会阻塞直到三次握手成功或者超时失败才返回
在进行 TCP 进行数据传输时,都不可避免的会经过这两个阶段:
- 三次握手建立连接
- 执行数据传输、双方读写
- 四次挥手释放连接
三次握手
在建立TCP连接时,需要经过三次交互,也成为三次握手(HandShake)。
- 客户端发起连接请求,发送 SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认
- 服务器收到SYN包后,必须确认客户的 SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态
- 客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此后客户端和服务器进入ESTABLISHED状态,双方可以开始传送数据。
传输数据过程:
-
超时重传超时重传机制用来保证TCP传输的可靠性。每次发送数据包时,发送的数据报都有seq号,接收端收到数据后,会回复ack进行确认,表示某一seq 号数据已经收到。发送方在发送了某个seq包后,等待一段时间,如果没有收到对应的ack回复,就会认为报文丢失,会重传这个数据包。
-
快速重传接受数据一方发现有数据包丢掉了。就会发送ack报文告诉发送端重传丢失的报文。如果发送端连续收到标号相同的ack包,则会触发客户端的快速重 传。比较超时重传和快速重传,可以发现超时重传是发送端在傻等超时,然后触发重传;而快速重传则是接收端主动告诉发送端数据没收到,然后触发发送端重传。
-
流量控制这里主要说TCP滑动窗流量控制。TCP头里有一个字段叫Window,又叫Advertised-Window,这个字段是接收端告诉发送端自己 还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。 滑动窗可以是提高TCP传输效率的一种机制。
-
拥塞控制滑动窗用来做流量控制。流量控制只关注发送端和接受端自身的状况,而没有考虑整个网络的通信情况。拥塞控制,则是基于整个网络来考虑的。考虑一下这 样的场景:某一时刻网络上的延时突然增加,那么,TCP对这个事做出的应对只有重传数据,但是,重传会导致网络的负担更重,于是会导致更大的延迟以及更多 的丢包,于是,这个情况就会进入恶性循环被不断地放大。试想一下,如果一个网络内有成千上万的TCP连接都这么行事,那么马上就会形成“网络风 暴”,TCP这个协议就会拖垮整个网络。为此,TCP引入了拥塞控制策略。拥塞策略算法主要包括:慢启动,拥塞避免,拥塞发生,快速恢复。
四次挥手断开连接:
在释放连接时,由于TCP是全双工的,因此最后要由两端分别进行关闭,这个流程如下:
-
客户端发送一个FIN,用来关闭客户端到服务器的数据传送,客户端进入FINWAIT1状态。
-
服务器收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),服务器进入CLOSEWAIT状态,而客户端进入FINWAIT2状态。
-
服务器发送一个FIN,用来关闭服务器到客户端的数据传送,服务器进入LASTACK状态。
-
客户端收到FIN后,客户端进入TIMEWAIT状态,接着发送一个ACK给服务器,确认序号为收到序号+1,服务器进入CLOSED状态,完成释放。
到这里TCP系列:TCP 干货,分享完毕了,快去试试吧!下一波将分享=>TCP系列:TCP 干货三次握手和四次挥手的一些问题!
最后
-
更多参考精彩博文请看这里:《陈永佳的博客》
-
喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!——-
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/97861.html