禅与计算机 禅与计算机
首页
  • Java基础

    • 聊一聊java一些核心知识点
    • 聊聊java面向对象核心知识点
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 写作

    • 写好技术博客的5大核心原则:从认知科学到AI工具的全流程指南
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • 从Lucene到Elasticsearch:进化之路
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

sharkchili

计算机禅修者
首页
  • Java基础

    • 聊一聊java一些核心知识点
    • 聊聊java面向对象核心知识点
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 写作

    • 写好技术博客的5大核心原则:从认知科学到AI工具的全流程指南
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • 从Lucene到Elasticsearch:进化之路
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 计算机组成原理

  • 操作系统

  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
      • 前言
      • OSI7层模型
      • 实践-基于抓包了解WireShark的基本使用
        • 安装WireShark
        • 快速抓包了解一下抓包的技巧
        • 抓到一个HTTP协议的数据包
      • 理论篇-关于TCP的一些常见问题解答
        • TCP如何加急数据包
        • SYN-SEND这个标志位的含义
        • PSH和URG两个标志位的区别是什么
        • 为什么TCP需要进行3次握手?
        • 随机序号 ISN是什么?
        • TCP报文中的序列号序列号如何排序
        • 什么是后退N协议
        • 选择重发协议是什么
        • 流水线传输是什么
        • 捎带确认是什么
        • TCP如何做到流量控制
        • TCP拥塞控制是什么意思
        • 流量控制和拥塞控制的区别
        • TCP的三次握手交互流程是什么样的
      • 四次挥手
        • 为什么结束通信需要四次挥手?
        • 四次挥手图解
      • TCP的日常故障排查
        • TCP报文中的控制位出现RST怎么办?
        • 出现Retransmission
        • 出现大量SYN同步报文
      • tcp相关例题
        • 发送方连发 1000 2000 3000 4000 5000 6000的报文,接收方回复ack序列号为4000,若为gbn需发送那些报文?若为sr则又要发送那些报文?
        • a向b发送数据,序列号分别是70 110。那么报文字节数是多少?b收到第一个报文段的确认号是多少? 第2次收到报文后回复180,问第二个报文段长度是多少?a发送的第一个报文丢失,用累计确认的方式回复的确认好为多少?
        • 拥塞问题为何超时重传无法解决?
      • 实验1(假如TCP刚刚建立连接的syn包就丢了)
        • 模拟步骤
        • 客户端开个tcpdump监听请求
        • 将服务器的网络断开
        • 客户端curl一下服务端地址
        • 取出抓到的包分析
        • 从操作系统内核配置查看原因
      • 实验2(假如服务端ack包丢失)
        • 模拟步骤
        • 开启服务端所有服务
        • 客户端开个tcpdump监听http请求并rejectServer.pcap
        • 客户端将iptables对于服务ip的ack包drop掉
        • 使用curl请求服务端地址
        • 查看抓包结果
        • 从操作系统内核了解原因
      • 实验3(假如服务端没收到客户端的ack)
        • 操作步骤
        • 将原本客户端的iptables禁止的规则改为accept
        • 设置服务端drop客户端的ack确认包
        • 客户设置tcpdump监听http请求
        • 抓包查看结果
        • 从系统内核查看原因
      • 小结
        • 更多的内核参数
        • 关于iptables
        • 关闭进程相关
      • 参考文献
  • 运维

  • 编码最佳实践

  • 计算机基础
  • 计算机网络
sharkchili
2026-03-25
目录

基于抓包详解TCP协议

[toc]

# 前言

这篇文章原文内容是笔者大学时网络系统集成的笔记,由于最近开始复习计算机网络基础,为了体系化知识,故将此文整理成一篇详尽的TCP详解博文。

# OSI7层模型

在正式了解TCP协议之前,我们需要对网络的层次划分有一个大体的认识,所以我们不妨来复习一下OSI七层模型,OSI七层模型自底向上的顺序为:

  1. 物理层:通过物理媒介将比特流数据传输到另一个设备中。
  2. 数据链路层:负责将上层的数据封装成数据帧。
  3. 网络层:负责在不同的网络之间进行数据路由,确定源地址和目标地址,该层常见的协议为IP、ICMP、RIP、IGMP、OSPF。
  4. 传输层:负责将数据进行分段或者重组,并提供端到端之间的可靠或者不可靠传输,并且该层还支持对错误数据的检测和纠正,常见协议是TCP、UDP协议。
  5. 会话层:负责建立、维护、终止程序之间的会话,该层同样还负责数据的同步和恢复功能,常见协议为SSL、TLS、DAP等。
  6. 表示层:负责传输数据的编码和解码,以便不同程序可以理解传输的内容,所以层也支持数据的加密和解密确保数据的安全性。
  7. 应用层:应用层即为用户提供服务的一层,即为应用程序提供服务的一层,常见的协议有HTTP、FTP、DNS、SSH等。

# 实践-基于抓包了解WireShark的基本使用

# 安装WireShark

  1. 两台可互通的centos(这里笔者用192.168.0.127模拟客户端、192.168.0.128模拟服务端)、一个spring boot web项目、可进行curl、telnet、ping、tcpdump等命令
  2. 一个抓包工具wireshark 关于wireshark的安装使用,笔者建议参考这篇文章 网络分析工具——WireShark的使用(超详细) (opens new window)

# 快速抓包了解一下抓包的技巧

在开始之前,我们先了解一下需求,我们希望在服务端即可ip为192.168.0.128的服务器上开启tcpdump命令,抓取127客户端的tcp包。

在这里插入图片描述

首先我们可以键入如下命令查看客户端的ip以及网口名称

ifconfig
1

由此确认,笔者客户端所使用的ip为192.168.0.127网口名称为ens

在这里插入图片描述

然后使用tcpdump监听对应网口的ping 192.168.0.128的数据包 ,这里笔者就简单介绍一下下面命令的含义。 -i即指定抓包的网口,由于上文笔者使用ifconfig看到网口名为ens33,所以这里-i所指定的端口就是ens33。 后续跟着一个icmp就是icmp协议,使用and拼接后续的条件这里指明了笔者目标服务器的ip 192.168.0.128。 然后我们再加一个-nn即可表示我们抓到的包不解析为主机名,显示ip和port即可。 最后一个-w ping.pcap意思为将抓到的数据包写到ping.pcap文件中

tcpdump -i ens33 icmp and host 192.168.0.128 -nn -w ping.pcap

1
2

关于tcpdump更多的命令参数选项如下所示:

选项 示例 说明
host、src host、dst host tcpdump -nn host 192.168.0.100 过滤出对应主机地址的数据包
port、src port、dst port tcpdump -nn port 80 过滤出对应端口的数据包
ip、ip6、arp、tcp、udp、icmp tcpdump -nn udp 过滤出对应协议的数据包
and、or、not tcpdump -nn host 192.168.0.100 and port 80 将多个条件组合起来的参数

完成上述抓包监听之后,我们使用客户端再开一个终端,ping目标服务器3次

 ping 192.168.0.128 -I ens33 -c 3

1
2

ping结束后,我们的将128服务器中的ping.pcap文件导到windows系统的wireshark。打开后可以看到客户端端发一个echo request,服务端就会回应一个echo reply。

在这里插入图片描述

我们不妨双击一个请求查看他的数据包的详细内容,可以看到wireshark的强大,他将物理层到网络层的所有信息都捕获到了,关于报文的具体内容笔者都已详尽注释,读者可以自行参考阅读。

在这里插入图片描述

然后我们不妨看看网络包中每一层的具体内容,先看看数据链路层,他指明了上层数据的类型,以及源mac地址和服务器(192.168.0.128)的mac地址

在这里插入图片描述

再来看看网络层抓到的内容

在这里插入图片描述

最后看看icmp协议,可以看到报文内容很简单,就是一个简单的echo request

在这里插入图片描述

总结一下,上文的数据分层结构如下图所示,每一层都会在数据包中添加一个头。

在这里插入图片描述

# 抓到一个HTTP协议的数据包

该实验是为了了解客户端和服务端进行HTTP协议交互时,网络数据包的交互流程。所以我们可以准备一个web进行实验。 因为笔者是Java开发,所以 准备一个spring boot的web应用部署到服务器后台运行,这里笔者从spring官网生成了一个jdk8版本的springboot应用,将端口设置为80端口,编写一个测试的web请求方法,完成后打包到服务器上。

在这里插入图片描述

这里我们就编写了一个简单的http请求方法

在这里插入图片描述

在服务器上测试接口过程如下。

curl 127.0.0.1/shark/hello

1
2

可以看到响应了一个hello world的字符串,我们终于可以抓包干活了

在这里插入图片描述

然后我们就用ip为127的客户端开个tcpdump监听本机关于192.168.0.128的http请求

tcpdump -i any and host 192.168.0.128 and port 80 -w http.pcap

1
2

完成上述命令后,我们客户端在开一个中断curl一下服务器(192.168.0.128)

curl 192.168.0.128/shark/hello
1

最终客户端在tcpdump的中断按住CTRL C终止监听,并将抓到的数据包的pcap文件导入wireshark中,于是我们就得到下图所示的文件。

在这里插入图片描述

我们可以看到正常的三次握手过程以外,还看到了http交互过程,在建立tcp连接后:

  1. 客户端会向服务端发送一个http请求,即一个get的请求。
  2. 服务端发一个tcp的ack数据包表示确认收到,再将一个text类型的数据发给客户端
  3. 客户端会给服务端一个ack确认本次会话就结束了。

在4次挥手时,我们看到一个很奇怪的现象,看着我们抓包的情况来看,tcp断开连接好像3次交互就够了,难道书本上教的内容是错误的嘛? 并不是,就以本次连接为例,由于http请求的数据不大,在断开连接的时候,服务端并没有要再传给客户端的数据,所以将在服务端向客户端发送确认报文ack时,捎带了fin数据包。这就造成了断开连接只要3次的情况。

当然,要是觉得这样看不够直观,我们完完全全可以使用wireshark自带的统计流程图看看tcp交互过程 如下图所示,点击流量图

在这里插入图片描述

再将流类型改为tcp flows即可,是不是很直观呢?

在这里插入图片描述

这样3次握手、建立连接、4次挥手的过程就很直观了。

在这里插入图片描述

# 理论篇-关于TCP的一些常见问题解答

# TCP如何加急数据包

将PSH(push)置为1,即将数据直接向上层传输,这一点我们可以在HTTP请求的数据包的传输层看到这个标志位。

在这里插入图片描述

# SYN-SEND这个标志位的含义

SYN-SEND意味同步发送,因为要求同步,所以我们要在建立连接时,将同步位syn为同步位设置为1。

# PSH和URG两个标志位的区别是什么

URG标志位表示紧急数据指针有效。在TCP协议中,有些数据可能需要优先传输,比如某些控制信息或者紧急数据。如果发送方需要发送这些紧急数据,就可以设置URG标志位,并指定紧急数据的位置。当接收方接收到URG标志位并识别出紧急数据指针时,就会立即处理这些紧急数据,以保证其能够及时被处理。

在这里插入图片描述

PSH标志位表示发送方要求接收方立即将缓冲区中的数据发送出去。在传输数据时,通常会先将数据存储到发送方的缓冲区中,等到缓冲区填满或者超时后再发送出去。但是,如果发送方使用了PSH标志位,就表示它希望接收方立即将缓冲区中的数据发送出去,而不需要等到缓冲区填满或者超时。这样可以减少延迟,提高数据传输效率。

在这里插入图片描述

因此我们可以理解为PUSH用于提高数据传输效率,而URG 则是为了加速数据处理。

# 为什么TCP需要进行3次握手?

由于tcp要实现全双工通信,所以要求双方都具备收发功能,这就要求第一次建立请求之后,双方都要各自进行一次收发。 这些内容我们完完全全可以在上文的抓包中得到印证。

# 随机序号 ISN是什么?

三次握手的协商参数

# TCP报文中的序列号序列号如何排序

切分后的报文段的第一个字节字节号作为数据包的序列号。

# 什么是后退N协议

为保证tcp可靠传输的一个方案,其特点就是累计确认,例如 接受方受到连续按序的五个报文时候发送确认消息6,就代表前五个数据包都收到了,期待第六个数据包。

在这里插入图片描述

# 选择重发协议是什么

哪个分组损坏或者没收到就要求发送方重发哪个分组。

# 流水线传输是什么

每次批量发送数据包,由于与批量传输,所以适用于通信状况比较稳定的场所。但数据包不可达时,选用后退n或者选择重发进行数据重传。

# 捎带确认是什么

接收方接收后回复ack时顺带一些需要发送给发送方的数据。

# TCP如何做到流量控制

滑动窗口,在tcp建立连接时,接收方会高速发送方他的接收窗口的大小,发送方的发送窗口就会根据接收方所能接受的窗口动态的调整窗口大小。 工作原理即接收方发送确认包时,发送方动态向右滑动窗口继续发送新数据,且该窗口始终保持接收方的当前所能接受的窗口大小。

在这里插入图片描述

# TCP拥塞控制是什么意思

其核心就是用慢启动算法,拥塞窗口根据网络拥塞程度动态变化,一旦网络拥塞就减小拥塞窗口,以减少发送到网络中的报文数量。 这其中有个关键字 MSS(最大报文段大小),取值一般取1460(tcp头和ip头各占20字节,加起来1500刚好是以太网标准的mtu)

# 流量控制和拥塞控制的区别

流量控制是收发两端的问题,即点对点问题,通过抑制发送方发送数据的大小进行控制。这其中就涉及到一个重要的概念-缓存,如下图所示:通信两端在每道工序中货扮演生产者或扮演消费者的角色,发送方按照接收方所能容纳的大小将数据放入缓存,缓存满了进入下一工序,并提醒下部工序的角色做好准备,正是这样以套紧密联接的分工,才保证的流量控制。

在这里插入图片描述

而拥塞控制是全局性问题,无法做到完全解决,只能说在收发两端使用慢启动和拥塞避免的手段尽可能的优化。

# TCP的三次握手交互流程是什么样的

TCP建立3次握手时需要考虑两种情况,当传输的数据长度为0时,交互过程如下:

  1. 建立连接者a发送一个同步号序列为1的报文。序列号为x。
  2. 接收方b收到报文后,生成确认位,值为a发送的序列号x+1,同样生成一个序列号y。
  3. a收到报文后,同样生成一个确认位值为b的序列号y+1,序列号为上一次发送的序列号x+1.

在这里插入图片描述

再来说说第二种情况,假如发送的数据长度不为0,每次接收的序列号则都是基于对方的序列号+长度+1:

在这里插入图片描述

# 四次挥手

# 为什么结束通信需要四次挥手?

因为通信是双向的,所以需要经过双方都确认才可,而结束是单方面要求,必须经由双方各自全双工通道都断开连接才可。

# 四次挥手图解

四次挥手如下图所示:

  1. 发起结束方a发起结束,数据包中结束为FIN设置为1,序列号为u。
  2. 结束方b收到后发起确认,却认为ACK为1,ack值为对端序列号u+1,并生成自己数据包的序列号v,开始将剩余数据发送完成。
  3. 结束方b完成所有数据后,通知a可以关闭连接了,于是发送的报文FIN为1和ACK也为1,代表确认建议结束了,ack的值为a的序列号u+1,生成本地会话序列号为w。
  4. a收到确认结束后,发送收到通知,所以报文ACK为1,序列号基于自己第一次发送的数据包u+1,ack的序列号则是b发送的序列号w+1。

在这里插入图片描述

# TCP的日常故障排查

# TCP报文中的控制位出现RST怎么办?

可能是对方tcp服务关闭,确认一下对方的TCP服务程序是否关闭。

# 出现Retransmission

可以推测大概是以下3种原因:

  1. 接受方没有收到。
  2. 接受方收到,但确认报文丢失。
  3. 接收方收到有问题的报文。

# 出现大量SYN同步报文

如果这种情况伴随着我方发送同步报文后无响应,大概率存在Ddos攻击(分布式拒绝式服务攻击)

# tcp相关例题

# 发送方连发 1000 2000 3000 4000 5000 6000的报文,接收方回复ack序列号为4000,若为gbn需发送那些报文?若为sr则又要发送那些报文?

答:gbn回4000则是要求发送4000代表前4000的都收到了,4000字节段的报文可能出现问题,要求对方发送4000之后的报文。 而sr则是代表3000段收到了要求发4000,其他报文段没有回复确认同样需要发送。即sr回复4000需要发送1000 2000 4000 5000 6000

# a向b发送数据,序列号分别是70 110。那么报文字节数是多少?b收到第一个报文段的确认号是多少? 第2次收到报文后回复180,问第二个报文段长度是多少?a发送的第一个报文丢失,用累计确认的方式回复的确认好为多少?

答:报文字节数:110-70=40 由公式可知b收到第一个报文后的确认号为:70+40+1=111 第二个报文长度为180-110=70 用累计确认的方式,则可以认为第2个起报文都没收到,直接回复70。

# 拥塞问题为何超时重传无法解决?

答:网络拥塞后,将超时的包再次重传只会使得原本阻塞的网络环境变得更加糟糕,进而导致网络崩坏。

# 3个抓包实验巩固TCP基础

# 实验1(假如TCP刚刚建立连接的syn包就丢了)

# 模拟步骤

# 客户端开个tcpdump监听请求

tcpdump -i any tcp   and host 192.168.0.128 and port 80 -w synClose.pcap

1
2

# 将服务器的网络断开

这步无需解释,笔者直接在虚拟机中将网络关掉,或者直接关机

# 客户端curl一下服务端地址

如下所示,为了更直观的看到时间,笔者在命令前后加了date

date;curl 192.168.0.128/shark/hello;date

1
2

# 取出抓到的包分析

从抓出来的数据来看,由于我们将服务器的网络断了,导致客户端的syn请求没有收到服务端的ack,所以客户端以为服务端没有收到,就重试了5次。

在这里插入图片描述

# 从操作系统内核配置查看原因

为什么是5次呢?我们可以通过操作系统内核的配置中一探究竟

键入以下命令

cat /proc/sys/net/ipv4/tcp_syn_retries
1

输出

5
1

这就是为什么一旦syn没有收到对端的ack,就会超时重试的次数

如果读者不相信这个结果可以改变结果,不妨修改这个值

 echo 2 > /proc/sys/net/ipv4/tcp_syn_retries

1
2

可以看到经过笔者的修改后,TCP建立连接丢包,就会重试两次。

在这里插入图片描述

还有一点读者需要留心,就是重试等待时间RTO,如下图所示,可以看出每次重试的时间都会基于上一次的等待时间乘2

在这里插入图片描述

# 实验2(假如服务端ack包丢失)

# 模拟步骤

# 开启服务端所有服务

这里只是做个补充,由于笔者上一个实验将服务器网络断开了,这里要再次将其连接回来

# 客户端开个tcpdump监听http请求并rejectServer.pcap

tcpdump -i any tcp   and host 192.168.0.128 and port 80 -w rejectServer.pcap
1

# 客户端将iptables对于服务ip的ack包drop掉

iptables -I INPUT -s 192.168.0.128 -j DROP
1

# 使用curl请求服务端地址

date;curl 192.168.0.128/shark/hello;date

1
2

# 查看抓包结果

可以看到下面这样一张图,是不是很不直观,无妨,我们使用tcp flows查看一下结果

在这里插入图片描述

首先我们看看客户端,除去第一次syn的数据包以外,由于我们把服务端的确认包拒绝了,导致客户端以为他发的syn数据包没有被收到,遂重试了5次,可以看到RTO也是基于上次等待时间乘2,符合我们上个实验所得结论

在这里插入图片描述

可以看出,服务端在第一次发syn+ack(同步+确认收到)包之后,每次客户端发syn包都会回复一个syn+ack(同步+确认收到)包,在下图用红色箭头所指。

一旦超时没有被收到就会再发一次,下图用蓝色箭头所指。如此往复5次,最终确认无法和对方建立连接。直接放弃建立连接。

需要补充一点,可能会有读者疑问,为什么iptables明明drop这个数据包,为什么tcpdump还能看到,如下所示,数据包流向iptabls之前会经过tcpdump,所以对于input的数据tcpdump可以看到,而出去的就看不到了

进来的顺序 Wire -> NIC -> tcpdump -> netfilter/iptables
出去的顺序 iptables -> tcpdump -> NIC -> Wire

在这里插入图片描述

# 从操作系统内核了解原因

键入以下命令,我们可以得到数字5,由此得出上文中syn+ack包重试次数为5,同样的,如果读者不信,可以将这个值修改一下抓包看看结果,这里就不做演示了

cat /proc/sys/net/ipv4/tcp_synack_retries
1

# 实验3(假如服务端没收到客户端的ack)

# 操作步骤

# 将原本客户端的iptables禁止的规则改为accept

由于上一个实验将规则drop了,这里需要改为accept

iptables -I INPUT -s 192.168.0.128 -j ACCEPT
1

# 设置服务端drop客户端的ack确认包

命令如下所示意为将客户端的确认包丢掉

iptables -I INPUT -s  192.168.0.127 -p tcp --tcp-flag ACK ACK -j DROP

1
2

# 客户设置tcpdump监听http请求

date;curl 192.168.0.128/shark/hello;date

1
2

# 抓包查看结果

同样看到密密麻麻的一排,我们将其使用统计图的形式来分析结果

在这里插入图片描述

首先看看服务端的数据包,可以看到由于ack包被drop了,服务端认为自己的syn+ack没有被收到,遂按照上文tcp_synack_retries重试了5次,发现失败,遂不了了之

在这里插入图片描述

所以我们在服务端键入如下指令

netstat -napt |grep 192.168.0.127
1

输出

tcp        0      0 192.168.0.128:80        192.168.0.127:58696     SYN_RECV   
1

我们都知道客户端向服务端发送syn包之后,客户端会进入SYN_SEND,等待服务器确认包 当服务端收到syn包后,立刻回一个syn+ack,此时服务端的状态就是SYN_RECV 意为收到客户端的syn包,发送一个ack等待客户端确认,也就是上文的状态。

再来客户端的数据包可以看到笔者矩形所圈的部分就是客户端发送ack后,认为已经和服务端建立连接了此时状态为established。这一点我们可以按照如下指令即可看到结果

netstat -napt |grep 192.168.0.128
1

遂发送了一个http请求,结果没收到结果,发送了一个psh+ack再找服务端要一次,还是没要到,这时候客户端就认为这条连接有问题了。 所以后面15箭头所示的,超时重传请求15次去确认这条tcp连接是否可用。

在这里插入图片描述

# 从系统内核查看原因

这个15我们可以键入以下命令查看

cat /proc/sys/net/ipv4/tcp_retries2

1
2

需要补充的是tcp_retries2意思为在丢弃激活(已建立通讯状况)的TCP连接之前﹐需要进行多少次重试。默认值为15

# 小结

碍于本文篇幅原因,很多读者可能对文章某些内容云里雾里,以下便列出笔者认为阅读本文所需要补充的知识

# 更多的内核参数

tcp_syn_retries等参数详解 (opens new window)

# 关于iptables

Linux 防火墙教程:IPTables 表、链、规则基础 (opens new window)

# 关闭进程相关

Linux下如何通过一行命令查找并杀掉进程 (opens new window)

# 参考文献

ICMP属于哪层协议 (opens new window)

SYN_RECV的意思 (opens new window)

一文读懂OSI七层模型和TCP/IP五层模型 (opens new window)

TCP 实战抓包分析 (opens new window)

编辑 (opens new window)
上次更新: 2026/03/26, 01:05:31
网卡数据包处理指南
Linux性能问题排查最佳实践

← 网卡数据包处理指南 Linux性能问题排查最佳实践→

最近更新
01
基于EasyExcel实现高效导出
03-25
02
从开源框架中学习那些实用的位运算技巧
03-25
03
浅谈分布式架构设计思想和常见优化手段
03-25
更多文章>
Theme by Vdoing | Copyright © 2025-2026 Evan Xu | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×
×