TCP
扫描二维码
随时随地手机看文章
TCP 的基本认识
TCP 中文又被称之为传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输层通信协议。这个特性的解释如下:- 面向连接的:面向连接也就是说
一对一
才能连接。 - 可靠的:无论网络中出现了什么变化,TCP都能保证一个报文一定能够到达接收端
- 字节流:消息是
没有边界的
,所以无论消息有多大都可以进行传输
OSI
参考模型的应用层、表示层、会话层,传输层和网络层是一一对应的,然后紧接着是网络接口层,网络接口层对应着 OSI
参考模型的 数据链路层、物理层。在说了 TCP/IP
的分层模型,紧接着来介绍下 TCP 的头部格式,它的头部格式如下所示:上图就是针对于 TCP 头部的一个示意图,下面对于几个概念进行解释:- 序列号:用来解决网络的乱序问题
- 确认应答号:指下一次期望收到的数据的序列号,用来解决不丢包的问题
- 控制位:
- ACK: 该位为 1 时,
确认应答
的字段变为有效,TCP规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 - RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接
- SYN: 该位为 1 时,表示期望建立连接,并在其
序列号
的字段进行序列号初始值的设定 - FIN :该位为 1 时,表示今后不再有数据发送,希望断开连接。
- Socket:由
IP
地址和端口号组成 - 序列号:用来解决乱序问题
- 窗口大小:用来做流量控制
- 源地址
- 源端口号
- 目标地址
- 目标端口号
TCP 的运输连接
在前文中叙述了 TCP 是面向连接的协议,它是基于传输连接来传送 TCP 报文段,TCP 传输连接的建立和释放是每一次面向连接的通信中必不可少的过程,TCP 的运输连接主要有以下三个阶段:- 建立 TCP 连接
- 数据传送
- 释放 TCP 连接
TCP 建立连接
TCP 建立连接要解决的是以下三个问题:- 使得 TCP 双方能够确知对方的存在;
- 使得 TCP 双方能够协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等);
- 使得 TCP 双方能够对运输实体资源(如缓存大小、连接表中的项目等)进行分配
SYN=1,seq=x
。TCP 客户端进程首先创建传输控制块,然后,在打算建立连接时,向TCP服务器进程发送TCP连接请求报文段,并进入同步已经发送状态。TCP连接请求报文段首部中的同步位SYN被设置为1,也就表明这是一个 TCP 连接请求报文段,序号字段 seq 被设置了一个初始值,作为 TCP 客户进程所选择的初始序号,(这里要注意的是:TCP规定 SYN 设置为 1 的报文段不能够携带数据 ,但是要消耗掉一个序号,由于 TCP 连接建立是由 TCP 客户端主动发起的,因此称之为主动打开连接)紧接着:,对应着第二个箭头,SYN=1 ACK=1 seq=y ack=x 1
。TCP 服务端如果同意客户端建立连接,则向 TCP 客户端进程发送 TCP 连接请求确认报文段,并进入同步已经接收状态最后:,TCP 客户端收到连接请求确认报文段之后,还需要向 TCP 服务进程发送一个普通的 TCP 确认报文段,并进入连接已建立状态。该报文是 ACK=1 seq=x 1 ack=y 1
,也就表明这是一个普通的 TCP 确认报文段。(普通的 TCP 确认报文段可以携带数据,但是如果说当前的 TCP 确认报文段不携带数据,那么也就不消耗数据报文段的序号,也就是说下一个数据报文段的序号还是 x 1),当 TCP 服务端收到这个普通认报文段之后,TCP服务端也进入连接已建立状态,这时 TCP 客户端和 TCP 服务端都进入了连接已经建立状态,就可以开始传输数据了。上述就是一个三次报文握手建立连接的一个过程,那么分析到这里,就出现了一个问题,就是说当 TCP 服务端发送连接请求确认报文段之后,当 TCP 客户端收到这个报文,难么就进入连接已建立状态了,这个时候直接发送数据不就行了,为什么还要再次发送一个 TCP 普通确认报文段呢?这是为什么?要解释这个问题,那首先假设当前 TCP 建立连接采用的是两报文握手连接,那么在 TCP 客户端发送连接请求报文段之后,TCP 服务器接收到连接请求报文段就进入连接已经建立状态,进一步 TCP 服务端发送连接请求确认报文段,这个时候,TCP 客户端收到报文之后,就也进入连接已经建立状态。然后,基于此,我们来看下面这样一个情况:如上图所示,由于 TCP 客户端发送的第一个连接请求报文段没有能够成功发送出去,TCP 服务端没有能够接收到这个报文段,这个时候,TCP客户端又重新发起了一个连接请求报文段,依据刚刚所说的过程,TCP 服务器在接收到这个报文段之后,就进入了连接已经建立状态,紧接着,客户端也进入了连接已经建立状态,就可以进行数据传输了,但是,这个时候,由于之前的 TCP 连接请求报文发送失败,导致的超时重传,在TCP已经释放连接的时候,TCP 客户端收到连接请求报文段,进入连接已经建立状态,但是这个时候对于 TCP 客户端来说,它已经关闭连接了,无法进入连接已经建立状态,这样也就会导致 TCP 服务器白白的在干等,在浪费资源。这也就是为什么采用三次报文握手,而不采用两次报文握手的原因。