开发者

Linux网络--传输层--TCP协议基础详解

目录
  • 一、TCP协议格式
    • TCP与UDP的对比
  • 二、TCP协议机制
    • 三、确认应答机制
      • 四、捎带应答
        • 五、三次握手和四次挥手
          • 1、应用层行为
          • 2、三次握手—建立连接
          • 3、四次挥手—断开连接
        • 总结

          一、TCP协议格式

          Linux网络--传输层--TCP协议基础详解

          TCP(传输控制协议)报文结构是网络通信中重要的基础概念,用于实现可靠的数据传输

          源端口与目的端口

          • 作用:标识通信的两端进程(范围:0~65535)
          • 示例:HTTP默认使用80端口,HTTPS使用443端口

          序号

          • 作用:标记本报文段中数据的第一个字节在整个数据流中的位置,用于保证数据有序传输
          • 特点:SYN标志位为1时,序号为初始序号(ISN),后续序号递增

          确认序号

          • 作用:期望收到的下一个字节的序号,表示已成功接收该序号之前的数据
          • 规则:确认号 = 已接收数据的最后一个字节序号 + 1

          首部长度

          • 作用:指示TCP头部的长度(以4字节为单位),最大值为60字节(默认20字节)
          • 原因:由于选项字段的存在,头部长度可能变化

          标志位

          用来区分TCP报文的类型

          • URG:紧急指针有效,通知接收方优先处理紧急数据
          • ACK:确认号是否有效
          • PSH:通知接收方立即将数php据提交给上层应用,即从TCP缓冲区读走
          • RST:重置连接,用于异常中断
          • SYN:同步序号,用于请求建立连接
          • FIN:终止连接,用于断开连接

          窗口大小

          • 作用:告知发送方当前接收方的可用缓冲区大小,用于流量控制
          • 单位:字节数,范围0~65535(通过窗口扩大因子可扩展)

          校验和

          • 作用:验证TCP报文段(包括头部和数据)在传输过程中是否损坏
          • 计算范围:TCP头部、数据部分,以及伪首部(包含IP地址和协议号)

          紧急指针

          • 作用:当URG标志位为1时,若当前段起始序列号为seq,紧急指针为ptr,则紧急数据的范围就是seqseq + ptr - 1
          • 注意:紧急数据会被识别并提前处理,但紧急数据是TCP中的一种特殊机制,实际中较少使用

          选项与填充

          常见选项

          • 最大段长度:协商每次传输的最大数据量
          • 时间戳选项:用于计算往返时间和防止序号回绕
          • 填充:确保头部长度为4字节的整数倍

          数据部分

          • 内容:封装上层协议(如HTTP、FTP)的数据
          • 注意:TCP头部不含长度字段,数据长度通过IP头部的总长度减去IP头部长度和TCP头部长度计算得出

          TCP与UDP的对比

          特性TCPUDP
          连接性面向连接(需三次握手)无连接(直接发送)
          可靠性可靠(重传、校验)不可靠(尽力而为)
          首部开销20~60字节(含选项)8字节
          适用场景文件传输、HTTP等视频流、DNS查询等

          通过以上结构,TCP能够实现可靠、有序、流量可控的数据传输,是互联网核心协议之一

          二、TCP协议机制

          Linux网络--传输层--TCP协议基础详解

          TCP拥有发送缓冲区和接收缓冲区两个缓冲区,发送信息的流程是:

          • 写入缓冲区:应用程序需要发送信息时,将信息写入用户缓冲区
          • 写入内核:调用wirte函数,将信息从用户缓冲区复制到发送缓冲区
          • 发送数据:通过网卡和内核TCP模块处理将数据存入另一用户的接受缓冲区
          • 写入用户区javascript调用read函数,将信息从接收缓冲区拷贝到用户缓冲区中
          • 应用程序获取数据:应用程序从用户缓冲区读取数据

          这里发送和接收的数据就是上面我们提到的协议格式下的报文

          三、确认应答机制

          TCP确认应答机制是编程客栈确保数据可靠传输的核心机制之一,也是区别于UDP的核心特点之一,在保证可靠性的同时,尽可能优化传输效率

          基本概念

          • 作用:接收方通过发送确认消息,告知发送方数据已成功接收,避免数据丢失
          • 可靠性保证:发送方在超时未收到确认消息时,会重传数据,叫做超时重传

          工作流程

          序号

          • 每个TCP报文段都会携带一个序号,标识该段数据在数据流中的位置

          确认号

          • 接收方通过确认消息返回确认号,表示下一个期望接收的数据序号
          • 规则:确认号 = 已成功接收的最后一个字节序号 + 1
            • 示例:若接收方成功接收序号1000~1999的数据段,确认号为2000,表示期望接收后续数据

          确认应答机制

          • 单次确认:发送方发送数据后,等待接收方的确认消息
          • 批量确认:滑动窗口技术允许发送方连续发送多个数据段,接收方只需确认最后一个连续收到的序号,也叫累积确认

          确认类型

          累积确认

          • 特点:接收方仅确认最后一个连续收到的数据段,忽略中间丢失的段
          • 优点:实现简单,减少确认消息数量
          • 缺点:若中间某个段丢失,发送方需重传后续所有段,这也叫做线头阻塞

          选择性确认

          • 机制:接收方通过选择性确认选项告知发送方哪些段已接收,哪些段丢失
          • 优点:发送方仅重传丢失的段,避免冗余重传
          • 适用场景:高带宽延迟网络,如卫星链路

          优化策略

          延迟确认

          • 机制:接收方延迟发送确认消息(通常最多200ms),合并多个确认以减少网络流量
          • 适用场景:批量数据传输,如文件下载

          确认应答压缩

          • 机制:在高速网络中,减少冗余确认消息的发送频率

          示例说明

          • 发送方发送数据段:序号1000(1000字节) → 序号2000(1000字节) → 序号3000(1000字节),接收方收到序号1000和3000的段:
          • 发送确认应答 2000(累积确认,仅确认连续段),那序号2000和序号3000的数据段都会重传
          • 若支持选择性确认,额外告知序号3000已接收,发送方根据确认应答和选择性确js认,仅重传序号2000的段

          这个确认应答呢我有一个小技巧来记忆,发送方发送数据段之后,比如说发送了序号1000,它代表着1000~1999,那我下一个是不是就要要2000了,那么我们确认应答发送的就是2000

          四、捎带应答

          我们将捎带应答这个解释过程简化为两张图,黑色斜线表示通信双方,正常情况下如下图所示,左边给右边发送一个报文,右边要给左边一个应答,表示已经收到数据,当然这里的应答也是严格按照TCP报文结构来的,发送的也是一个完整的TCP报文(至少有报头),之后右边再给左边发送报文,左边再给右边发送一个应答

          Linux网络--传输层--TCP协议基础详解

          但是这样的效率会很低,在正常情况下,双方不会这样进行通信,而是将应答和要发送的TCP数据整合成一条报文,此时发送的这条报文既是应答又是数据,减少开支

          Linux网络--传输层--TCP协议基础详解

          五、三次握手和四次挥手

          1、应用层行为

          Linux网络--传输层--TCP协议基础详解

          这边我们举一个客户端和服务端的例子

          三次握手

          • 服务端应用层行为(服务器初始化):服务端是要先开启的,应用层通过调用socket分配一个文件描述符,然后调用bind函数将这个文件描述符与服务器地址端口绑定,然后调用listen函数进入监听状态,然后调用accept函数阻塞等待客户端的连接,此时服务端开启完毕
          • 客户端应用层行为(建立连接):客户端后开启,应用层通过调用socket分配一个文件描述符,然后调用connect函数向服务器发起将文件描述符与服务器地址端口连接请求,connect函数会发出SYN段并阻塞等待服务器应答(第一次握手)
          • 服务器收到客户端SYN,会应答一个SYN-ACK段表示同意建立连接(第二次握手)
          • 客户端收到SYN-ACK后会从connect函数返回,同时应答一个ACK段(第三次握手)

          数据传输

          • 建立连接后,TCP协议会提供全双工的通信服务,即同一条连接同一时刻,通信双方可以同时写同时读
          • 服务器从accept函数返回后立刻调用read函数,读socket就和读管道一样,没有数据就阻塞等待
          • 这时客户端调用write发送请求给服务器,服务器收到后从read返回,对客户端的请求进行处理,在此期间客户端调用read函数阻塞等待服务器的应答
          • 服务器调用write函数将处理结果发回客户端,再次调用read函数阻塞等待下一条请求
          • 客户端收到后从read函数返回,发送下一条请求
          • 以①~⑤循环

          四次挥手

          • 客户端调用close关闭连接,此时客户端会向服务器发送FIN段(第一次挥手)
          • 服务器收到FIN后,回应一个ACK,同时read返回0(第二次挥手)
          • read返回之后,服务器就知道客户端关闭了连接,也调用close关闭连接,这个时候服务器会向客户端发送一个FIN(第三次挥手)
          • 客户端收到FIN,返回一个ACK给服务器(第四次挥手)www.devze.com

          2、三次握手—建立连接

          三次握手的机制就是建立在捎带应答上的,捎带应答不仅是通信时的一种策略,并且是建立连接时的策略

          Linux网络--传输层--TCP协议基础详解

          三次握手也可以是四次握手,理由和上面一样,这里的第二次握手本来也是两条消息合并发送而已

          • 对于客户端来说,当我们将ACK发出了,我们就认为连接已经建立成功了,此时客户端的状态就是上上图的ESTABLISHED,建立描述该连接的客户端属性结构体就被建立了,我们TCP协议对于连接的管理当然也是先描述后组织的,此时客户端连接的属性结构体就通过指针被队列组织管理了
          • 对于服务器来说,在开启监听状态LISTEN后,收到建立连接报文SYN,会对客户端进行确认并请求建立连接ACK+SYN,然后在收到客户端确认报文ACK之后建立描述该连接的服务器属性结构体,然后这个结构体也会被管理起来

          3、四次挥手—断开连接

          Linux网络--传输层--TCP协议基础详解

          • 对于客户端来说,当没有数据要读取或发送的时候,发送结束报文FIN,进入等待状态1,FIN_WAIT1,然后一直等待,在接收到服务器的应答ACK后进入等待状态2,FIN_WAIT2,然后一直等待,在收到服务器FIN报文时,发送应答ACK并转为TIME_WAIT状态,等待一个2MSL(报文最大生存时间)的时间,然后进入CLOSED状态
          • 对于服务器来说,在接收到客户端发来的结束报文FIN之后,如果自己也没有啥要发给客户端的,那么发送应答ACK并转为等待状态CLOSE_WAIT,处理之前的数据,处理完后向客户端发送结束报文FIN,并转为最终回应状态LAST_ACK,在接收到客户端的ACK的报文后,关闭连接

          总结

          以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。 

          0

          上一篇:

          下一篇:

          精彩评论

          暂无评论...
          验证码 换一张
          取 消

          最新运维

          运维排行榜