【Linux】 -- TCP协议 (一)

这篇具有很好参考价值的文章主要介绍了【Linux】 -- TCP协议 (一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Tcp协议

TCP全称为 “传输控制协议”(Transmission Control Protocol)

TCP协议被广泛应用 其根本原因就是提供了详尽的可靠性保证 基于TCP的上层应用非常多 比如HTTP、HTTPS、FTP、SSH、MySQL等。

可靠性

为什么网络中会存在不可靠

冯诺依曼体系结构

【Linux】 -- TCP协议 (一)
这里的 输入设备 内存 输出设备 cpu这些硬件都是相互独立的

如果它们之间要进行数据交互 就必须要想办法进行通信 这几个设备是用“线”连接起来的

其中连接内存和外设之间的“线”叫做 IO总线 而连接内存和CPU之间的“线”叫做 系统总线

由于这几个硬件设备都是在一台机器上的 因此这里传输数据的“线”是很短的 传输数据时出现错误的概率也非常低

但如果要进行通信的各个设备相隔千里 那么连接各个设备的“线”就会变得非常长 传输数据时出现错误的概率也会大大增高 此时要保证传输到对端的数据无误 就必须引入可靠性

总之网络不可靠的根本原因就是 长距离传输数据使用的‘线’太长了 所以说数据在长距离传输的时候可能会遇到一些错误 而TCP就是在这种背景下诞生的 TCP就是一种可靠的协议

  • 单独的一台计算机可以看作成一个小型的网络 计算机上的各种硬件设备之间实际也是在进行数据通信 并且它们在通信时也必须遵守各自的通信协议 只不过它们之间的通信协议更多是描述一些数据的含义

为什么会存在UDP协议?

TCP协议是一种可靠的协议 而UDP是一种不可靠的协议

TCP是一种可靠的协议 这也就意味着TCP需要做更多的工作来保证数据传输的可靠 并且引起不可靠的因素越多 我们要保证可靠的成本就越高 其中常见的不可靠情况有丢包 乱序等 而我们的TCP由于要保证可靠所以说要想办法解决这些问题

UDP协议是不可靠的协议 这也就意味着UDP不需要考虑数据传输时需要处理的问题 因此UDP无论是使用还是维护都足够简单

但是虽然说TCP的使用比UDP更加复杂 但是TCP的效率缺不比UDP低

如果我们严格要求了数据在传输过程中可靠性 那么我们就必须采用TCP协议 如果说允许数据有一点点丢包的话我们就可以使用UDP协议

TCP的协议格式

TCP协议格式如下:
【Linux】 -- TCP协议 (一)

TCP报头当中各个字段的含义如下:

  • 源/目的端口号:表示数据是从哪个进程来 到发送到对端主机上的哪个进程
  • 32位序号/32位确认序号:分别代表TCP报文当中每个字节数据的编号以及对对方的确认 是TCP保证可靠性的重要字段
  • 4位TCP报头长度:表示该TCP报头的长度 以4字节为单位
  • 6位保留字段:TCP报头中暂时未使用的6个比特位
  • 16位窗口大小:保证TCP可靠性机制和效率提升机制的重要字段
  • 16位检验和:由发送端填充 采用CRC校验 接收端校验不通过 则认为接收到的数据有问题 (检验和包含TCP首部+TCP数据部分)
  • 16位紧急指针:标识紧急数据在报文中的偏移量 需要配合标志字段当中的URG字段统一使用
  • 选项字段:TCP报头当中允许携带额外的选项字段 最多40字节

TCP报头当中的6位标志位:

  • URG:紧急指针是否有效
  • ACK:确认序号是否有效
  • PSH:提示接收端应用程序立刻将TCP接收缓冲区当中的数据读走
  • RST:表示要求对方重新建立连接
  • SYN:表示请求与对方建立连接
  • FIN:通知对方 本端连接要关闭了

TCP报头在内核当中本质就是一个位段类型 给数据封装TCP报头时 实际上就是用该位段类型定义一个变量 然后填充TCP报头当中的各个属性字段 最后将这个TCP报头拷贝到数据的首部 至此便完成了TCP报头的封装

TCP如何将报头与有效载荷进行分离?

当TCP从底层获取到一个报文后 虽然TCP不知道报头的具体长度 但报文的前20个字节是TCP的基本报头 并且这20字节当中涵盖了4位的首部长度

  • 当TCP获取到一个报文后 首先读取报文的前20个字节 并从中提取出4位的首部长度 此时便获得了TCP报头的大小size
  • 如果size的字节大于20字节 则再次从报文中读取size - 20的数据 这些数据是选项大小
  • 读取完报头和选项之后剩下的就是有效载荷了

如果TCP报头当中不携带选项字段 那么TCP报头的长度就是20字节 此时报头当中的4位首部长度的值就为 5 (20 / 4 = 5)

TCP如何决定将有效载荷交付给上层的哪一个协议?

应用层的每一个网络进程都必须绑定一个端口号

  • 对于服务器来说,服务端进程必须 显示绑定一个端口号
  • 对于客户端来说,客户端进程由系统 动态绑定一个端口号

而我们的TCP报头中含有这么一个字段 十六位目的端口号

因为我们可以从该报头中提取十六位目的端口号 找到对应的应用级进程 进而将有效载荷交给对应的应用层进程进行处理

在内核中 端口号与进程ID之间的映射关系是用哈希的结构 传输层可以通过端口号快速找到其对应的进程ID

序号与确认序号

怎么才能确定对方收到我的消息

在进行网络通信时 一方发出数据之后 它不能够保证该数据被对端收到 因为在路上可能会遇到各种各样的问题 所以说我们必须想一种办法来确认自己的消息被对端收到了 而在我们现在的网络通信中我们采用的办法就是序号和确认序号 通俗点来说 当自己向对端主机发送信息的时候 对端会给你应答 这个应答就能说明你的消息被对方接收到了

在下面中 实线表示的是消息确认能够被对方收到 虚线表示的是消息不确认能够被对方收到

【Linux】 -- TCP协议 (一)
但是TCP协议需要保证的是通信双方的可靠性 虽然此时主机A能够保证自己上一次发送的数据被主机B可靠的收到了 但主机B也需要保证自己发送给主机A的响应数据被主机A可靠的收到了

因此主机A在收到了主机B的响应消息后 还需要对该响应数据进行响应 但此时又需要保证主机A发送的响应数据的可靠性

因为我们只有在收到对方的响应消息之后我们才能保证自己上一次发送的数据被对端可靠的收到 但是就像上面的图例一样 总会有一条最新的消息不能确认被收到

所以严格意义上来说 互联网中通信的时候不存在百分百的可靠性 因为双方通信的时候总有一条最新的消息得不到应答

但实际没有必要保证所有消息的可靠性

我们只要保证双方通信时发送的每一个核心数据都有对应的响应就可以了 而对于一些无关紧要的数据(比如响应数据) 我们没有必要保证它的可靠性

这种策略在我们的TCP中叫做确认应答机制

需要注意的是 确认应答机制并不是保证双方通信的可靠性 而是只要一方收到了另一方的应答消息 就说明它上一次发送的数据被另一方可靠的收到了

32位序号

如果双方在进行数据通信时 只有收到了上一次发送数据的响应才能发下一个数据 那么此时双方的通信过程就是串行的 效率肯定会很差

因此双方在进行网络通信时 允许一方向另一方连续发送多个报文数据 只要保证发送的每个报文都有对应的响应消息就行了 此时也就能保证这些报文被对方收到了

但是在连续发送多个报文的时候又会产生新的问题 报文到达的先后顺序

由于在发送报文的时候路径选择的不同 所以报文到达的时间不一定相同 也就是说先发的报文不一定会先到

TCP将发送出去的每个字节数据都进行了编号 这个编号叫做序列号

  • 比如现在发送端要发送3000字节的数据 如果发送端每次发送1000字节 那么就需要用三个TCP报文来发送这3000字节的数据
  • 此时这三个TCP报文当中的32位序号填的就是发送数据中首个字节的序列号 因此分别填的是1、1001和2001

此时接收端收到了这三个TCP报文后 就可以根据TCP报头当中的32位序列号对这三个报文进行顺序重排(该动作在传输层进行) 重排后将其放到TCP的接收缓冲区当中 此时接收端这里报文的顺序就和发送端发送报文的顺序是一样的了

  • 接收端在进行报文重排时 可以根据当前报文的32位序号与其有效载荷的字节数 进而确定下一个报文对应的序号

32位确认序号

TCP中的三十二位确认序号是告诉对方 我当前已经收到了哪些数据 你的数据下一次应该从哪里开始发

为什么要用两套序号机制?

主机A和主机B之间通信

A主机只发送数据 B主机只接收数据

那么此时A主机发送序号请求报文的时候 B主机只需要在相同字段填写相同的响应报文就可以了

但是我们的TCP是一种全双工通信协议 所以说在AB主机通信的过程中 B主机也有可能向A主机发送数据

那么此时我们就需要使用两套序号机制来区分序号和响应序号了

窗口大小

TCP的接收缓冲区和发送缓冲区

TCP协议本身是具有接收缓冲区和发送缓冲区的

【Linux】 -- TCP协议 (一)

  • 我们调用write和read函数的时候并不是直接从磁盘而是从内存缓冲区中读取数据 根本原因是因为磁盘的IO效率太低了

在应用层调用write函数的时候 实际上就是向TCP的发送缓冲区中写入数据 TCP协议会等待合适的时机发送

与此同时当TCP接收从网络中发送过来数据的时候并不是直接发送到应用层 而是拷贝到接收缓冲区中 等待应用层使用read函数来读取

当我们平时调用write函数的时候 它会将数据写入到TCP的数据缓冲区 当写入成功(或失败)之后它就会返回了 之后数据什么时候发送 怎么可靠的发送就是传输层的事情了 应用层并不关心

TCP的发送缓冲区和接收缓冲区存在的意义

发送缓冲区和接收缓冲区的作用:

  • TCP是一个要保证可靠性的协议 如果发送端没有收到确认的应答 发送的数据就会保存一段时间之后继续发送 直到收到应答这部分数据才被覆盖
  • 和UDP协议一样TCP协议也有接收缓冲区 这是因为应用层梳处理数据的速度是有限的 为了保证没来得及处理的数据不被直接丢弃所以说我们要设立接收缓冲区 数据在网络中传输是十分耗费时间和空间的 如果仅仅是因为没有即使处理就丢弃资源会造成对于网络资源极大的浪费

经典的生产者消费者模型:

  • 对于发送缓冲区来说 上层不断的调用系统函数发送数据 扮演者一个生产者的角色 下层不断的调用系统函数接收数据 扮演着一个消费者的角色 发送缓冲区就是一个交易场所
  • 对于接收缓冲区来说 下层不断的向接收缓冲区中写入数据 扮演一个生产者的角色 上层不断的调用系统函数接收数据 扮演者一个消费者的角色 接收缓冲区就是一个交易场所
  • 因此 引入发送缓冲区和接收缓冲区就相当于引入了两个生产者消费者模型 该模型将上层应用和底层通信进行了解耦 同时它的引入同时也支持了并发和忙闲不均

窗口大小

当发送端要将数据发送给对端的时候本质上是将自己发送缓冲区的数据发送到对端的接收缓冲区中

但是我们的缓冲区是有大小的 如果我们的发送缓冲区发送数据的速度大于接收缓冲区接收的数据那么我们的数据就会溢出就会造成丢包废弃数据的情况

TCP协议给出的解决方案就是窗口大小

TCP使用这十六位的窗口大小来表示自身接受缓冲区的大小 此时我们的发送端就可以通过该十六位窗口大小来判断自己应该发送多少数据 控制自己发送数据的速率

  • 窗口大小字段越大 说明接受端接受数据的能力越强 此时发送端发送数据的速率越快
  • 窗口大小字段越小 说明接收端接收数据的能力越弱 此时发送端发送数据的速率越慢
  • 窗口大小字段为零 说明接收端不能接收数据了 此时发送端应该停止发送数据 避免数据浪费

六个标志位

SYN

  • 报文当中的SYN被设置为1 表明该报文是一个连接建立的请求报文
  • 只有在连接建立阶段 SYN才被设置 正常通信时SYN不会被设置

ACK

  • 报文当中的ACK被设置为1 表明该报文可以对收到的报文进行确认
  • 一般来说 除了第一次发送请求连接的报文不需要设置ACK之外其余所有的报文都需要设置ACK 因为向对方发送的数据的时候也可以确认对方之前发送的一些数据

FIN

  • 报文当中的FIN被设置为1 表明该报文是一个连接断开的请求报文
  • 只有在断开连接阶段 FIN才被设置 正常通信时FIN不会被设置

URG

  • 当URG标志位被设置为1时 需要通过TCP报头当中的16位紧急指针来找到紧急数据 否则一般情况下不需要关注TCP报头当中的16位紧急指针

什么是十六位紧急指针?

  • 它其实就是紧急数据在报文中的偏移量 也就是说当紧急指针为0时紧急数据就在最前面 紧急指针越大偏移量越大 紧急数据就越在后面

紧急数据的大小有多少?

  • 紧急数据的大小一般只有一个字节

PSH

  • 报文中的PSH被设置为1就是在告知对方该数据要尽快的交付给上层

接收和发送缓冲区都有一个水位线的概念

【Linux】 -- TCP协议 (一)

我们假设水位线是一百字节 那么 只有当数据达到一百字节的时候才会让read函数读取数据 否则会一直阻塞住

这么设计的原因是 如果缓冲区中有一点数据就读取的话会造成内核态用户态之间频繁的切换 这样子就会造成计算机效率的浪费

但是如果说我们发送报文的时候携带了这个选项 实际上就是在告诉操作系统 我们希望这个数据尽快被应用层读取

RST

  • 报文中的RST被设置为1 表示希望重新建立连接
  • 在通信双方在连接未建立好的情况下 一方向另一方发数据 此时另一方发送的响应报文当中的RST标志位就会被置1 表示要求对方重新建立连接
  • 如果连接的过程中出现了任何的异常也会要求重新建立连接

确认应答机制 (ACK)

确认应答机制是TCP协议保证可靠性的机制之一

确认应答机制是由TCP报头中的32位序号和32位确认序号来保证的

值得我们注意的是确认应答机制并不会保证所有消息的可靠性 最后总会有一条最新的消息是无法被ACK的

超时重传机制

在双方使用TCP进行通信的时候 如果发送方发出的数据在一段时间内得不到应答 此时发送方就会重新发送 这就叫做确认应答机制

除了报头之外TCP协议还会通过一些代码来保证其可靠性

超时重传机制就是这些代码中的一个 在发送出一个数据之后TCP就会设置一个“闹钟” 如果在闹钟响之前收到应答这个闹钟就会关闭 如果在闹钟响了之后还没有收到应答就会触发超时重传机制 重发数据

丢包的两种情况

我们通过TCP协议可以确定一个报文是否到了对端 但是我们无法确定一个报文没有到达对端

丢包的情况之一就是这个报文根本就没有到达对端 此时发送端在一定时间内没有收到响应报文就会触发超时重传

丢包的另一种情况就是 报文其实发送到对端了 但是对方的响应报文在传输的时候丢了 此时发送端没有收到对面的响应报文也会进行超时重传

超时重传的等待时间

我们超时重传的时间不能设置的太长或者太短

  • 如果我们超时重传的时间设置的过长会导致数据丢失之后对面长时间得不到对应的数据 进而影响整体重传的效率
  • 如果我们超时重传的时间设置的过短会导致数据没有丢失还是会触发超时重传机制 此时对面就会收到大量的重复报文 甚至太短的话整个网络都可能会崩溃

Linux中会以500ms为一个单位进行控制 每次判定超时重发的时间都是500ms的整数倍

如果下次的数据依然没有得到应答那么此时的响应时间就是500ms * 2 同理如果下下次发送的数据还是没有得到应答此时的响应时间就是500ms * 4 以此类推 以指数的形式传递 但是如果时间累计到了一定的程度 那么TCP就会认为对面的主机出现了问题从而强制关闭连接

连接管理机制

TCP是面向连接的

TCP的可靠性机制并不是主机之间 而是连接之间的

TCP协议是基于连接的 保证可靠性传输的前提是建立一个连接

操作系统管理连接

连接是TCP协议的基础 有了连接才能保证可靠性 但是一台机器上可能会有大量的连接 所以说操作系统必须要对这些连接进行管理

在Linux中一定会有一个这样子描述连接的结构体 该结构体中有需要管理连接用的各项属性 每次创建一个连接在系统看来就是定义了一个结构体

系统中创建了结构体之后会将它们用双链表的形式连接起来 此时操作系统对于连接的管理在实际上就变为了对于双链表的增删改查

  • 建立连接

创建出一个连接结构体 并且填充它的各个字段 之后连接到双链表中

  • 删除连接

删除该连接对应的结构体文章来源地址https://www.toymoban.com/news/detail-483129.html

到了这里,关于【Linux】 -- TCP协议 (一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • socket套接字通信 TCP传输控制协议/IP网络协议 5.18

    B/S :浏览器和服务器 C/S :客户机和服务器 网络的层次结构和每层所使用协议的集合 网络采用分层管理的方法,将网络的功能划分为不同的模块 OSI模型: 共7种: 数据的封装与传递过程: 网络传输数据大小user data: 6~1460 网络传输中容易发生拆包和粘包,所以接收和发送的字节

    2024年02月05日
    浏览(65)
  • 【Linux】传输层协议:UDP和TCP

    但人不能永远浪漫下去,那会走向自我毁灭的。浪漫都是水字旁,会把人淹死的。人最终还是要进入一个规则体系,所谓,随心所欲不逾矩嘛 1. 在网络通信中,通信的本质实际就是两台主机上的进程在网络环境中进行通信,也就是数据的传输,而我们总说TCP/IP协议栈,这两个

    2024年02月12日
    浏览(36)
  • 【Linux 网络】 传输层协议之TCP协议 && TCP的三次握手和四次挥手

    传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议 基于TCP应用层协议 HTTP HTTPS SSH Telnet FTP SMTP 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去 32位序号/确认序号:TCP的确认应答机制要使用到的字段,保证TCP的可靠

    2024年02月14日
    浏览(40)
  • 网路原理-传输层UDP,TCP/IP(确认应答,超时重传,连接管理,三次握手,四次挥手,状态转换,流量控制,滑动窗口,拥塞控制,延时应答,捎带应答,异常情况,面向字节流)-网络层(IP协议,地址管理)

    本节重点 • 理解传输层的作⽤,深⼊理解TCP的各项特性和机制 • 对整个TCP/IP协议有系统的理解 • 对TCP/IP协议体系下的其他重要协议和技术有⼀定的了解 我们之前编写完了基本的 java socket ,要知道,我们之前所写的所有代码都在应⽤层,都是为了 完成某项业务,如翻译等。

    2024年04月15日
    浏览(43)
  • TCP 协议【传输层协议】

    [重要] 本文默认读者已经体系地学习过操作系统。 为了读者能更好地学习 TCP 协议,本文首先简单介绍 TCP 协议(是啥),然后再简述 TCP 的主要内容(干嘛的),最后再阐述 TCP 的各个细节(原理)。 与 UDP 不同,TCP(Transmission Control Protocol)则“人如其名”,可以说是对“

    2024年02月15日
    浏览(35)
  • 传输层协议——TCP协议 (详解!!!)

    目录 TCP的报文格式  1. 源端口号,目的端口号 和 udp 相同(前面文章介绍了udp)  2. 4位首部长度 —— TCP的报头长度  3. 选项 —— option (可选的:可以有,可以没有) 4.保留(6)位   5. 16位校验和 TCP协议 的相关特性  1.有连接  2.面向字节流 和 全双工 2.可靠传输 TCP可

    2024年02月06日
    浏览(28)
  • 【网络编程】传输层协议——TCP协议

    TCP报头当中各个字段的含义如下 源/目的端口号 :表示数据是从哪个进程来,到发送到对端主机上的哪个进程。 32位序号/32位确认序号 :分别代表TCP报文当中每个字节数据的编号以及对对方的确认,是TCP保证可靠性的重要字段。 4位TCP报头长度 :表示该TCP报头的长度,以4字

    2024年02月17日
    浏览(44)
  • C#TCP传输协议

    TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议 作用:CP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数

    2024年02月16日
    浏览(32)
  • 【网络】传输层TCP协议

    目录 一、概述 2.1 运输层的作用引出 2.2 传输控制协议TCP 简介 2.3 TCP最主要的特点 2.4 TCP连接 二、TCP报文段的首部格式 三、TCP的运输连接管理 3.1 TCP的连接建立(三次握手) 3.2 为什么是三次握手? 3.3 为何两次握手不可以呢? 3.4 TCP的连接释放(四次挥手) 3.5 为什么客户端在TIME

    2024年01月23日
    浏览(29)
  • 传输层——TCP协议

    目录 一、初步认识 二、TCP协议格式 2.1 初识协议格式  2.2 序号与确认序号 2.3 16位窗口大小 2.4 六个标志位 三、确认应答机制 四、超时重传机制 五、连接管理机制 5.1 三次挥手 5.2 四次挥手  六、流量控制 七、滑动窗口 八、拥塞控制 九、延迟应答 十、捎带应答 十一、面向

    2024年02月03日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包