前言

本文旨在通过形象的例子和实操,把无形的、虚拟的网络转为具体的、可视化的。带领网络小白一步步的掌握 TCP 三次握手核心知识点,为后续深入学习 TCP 协议打基础。

通俗版

如下图所示,小明(客户端)给小美(服务端)打电话,在经过互相询问和应答,确认通信畅通后,才开始愉快地聊天。(本例子不一定无懈可击主要是意会即可)

细节版

一个 TCP 报文段分为首部和数据两部分,TCP 所有的功能都体现在首部的各个字段中。

序列号:本报文段所发送数据的第一个字节的序号,在建立连接时会随机生成初始序列号 ISN(Inital Sequence Number)。

确认号:下一次应该收到的数据的序列号,若确认号为 N,则代表到序列号 N-1 为止的数据都已经正确收到。

控制位:

  • ACK:为 1 时确认号才生效,在建立连接后所有传送的报文段 ACK 均为 1。

  • SYN:为 1 时表示这是连接请求(SYN=1,ACK=0)或者连接接受(SYN=1,ACK=1)报文。

由于上述报文都未携带数据,即 len=0,所以响应的 ack 等于请求的 seq+1。

实战版

为了抓到比较纯净的包,我们实现一个简单的 TCP Server,接受客户端的请求并回复。

func main() {
// 监听端口
l, err := net.Listen("tcp", "0.0.0.0:8080")
if err != nil {
panic(err)
}
defer l.Close() for {
// 接受连接
conn, err := l.Accept()
if err != nil {
log.Printf("accept err: %s\n", err)
continue
}
go hello(conn)
}
} func hello(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 1024)
// 读数据
if _, err := conn.Read(buf); err != nil {
log.Printf("conn read err: %s\n", err)
return
}
log.Printf("%s\n", string(buf)) // 写数据
if _, err := conn.Write([]byte("hello, xiao ming.\n")); err != nil {
log.Printf("conn write err: %s\n", err)
return
}
}

客户端请求:

echo -n "hello, xiao mei." | nc 81.68.197.93 8080

使用 wireshark 分析(统计 - 流量图)可以清楚的看到三次握手的过程。

同时也能看到 seq 和 ack 的关系,在握手成功后发送了 len=16 的包后,然后 ack=17 表示序列号在 16 之前的数据都已经正确收到。

注意:ISN 是一个随机数,并不为 0,wrieshark 为了显示更友好,使用了相对序号,在鼠标右键选项中取消即可看到真正的序列号,如:Seq=3503481500。

握手包源文件下载地址

状态机

TCP 所谓的面向连接本质就是客户端和服务端的数据结构都各自维护了一个”连接状态“,三次握手期间状态变化如下:

LISTEN:服务端主动监听一个端口,等待客户端的连接请求

SYN-SENT:发送 SYN 包后的状态

SYN-RECEIVED:收到 SYN 包,且发送了 SYN+ACK 包后的状态

ESTABLISHED:连接建立成功

# 使用 netstat 命令查看当前系统的 TCP 连接状态
$ netstat -t
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 ubuntu:58824 39.156.66.18:http TIME_WAIT
tcp 0 0 localhost:20172 localhost:37276 ESTABLISHED

参考

图解TCP/IP(第5版)

计算机网络(第7版)谢希仁

酷壳 - TCP 的那些事儿(上)

循序渐进搞懂 TCP 三次握手核心的更多相关文章

  1. 一文彻底搞懂 TCP三次握手、四次挥手过程及原理

    原创文章出自公众号:「码农富哥」,欢迎收藏和关注,如转载请注明出处! TCP 协议简述 TCP 提供面向有连接的通信传输,面向有连接是指在传送数据之前必须先建立连接,数据传送完成后要释放连接. 无论哪 ...

  2. 小白都能看懂的tcp三次握手

    众所周知,TCP在建立连接时需要经过三次握手.许多初学者经常对这个过程感到混乱:SYN是干什么的,怎么一会儿是1一会儿是0?怎么既有大写的ACK又有小写的ack?为什么ACK在第二次握手才开始出现?初 ...

  3. 阿里二面,面试官居然把 TCP 三次握手问的这么细致

    TCP 的三次握手和四次挥手,可以说是老生常谈的经典问题了,通常也作为各大公司常见的面试考题,具有一定的水平区分度.看似是简单的面试问题,如果你的回答不符合面试官期待的水准,有可能就直接凉凉了. 本文 ...

  4. TCP三次握手原理,你真的了解吗?

    最近碰到一个问题,Client 端连接服务器总是抛异常.在反复定位分析.并查阅各种资料搞懂后,我发现并没有文章能把这两个队列以及怎么观察他们的指标说清楚. 问题描述 场景:Java 的 Client ...

  5. TCP 三次握手原理,你真的理解吗?

    最近,阿里中间件小哥哥蛰剑碰到一个问题——client端连接服务器总是抛异常.在反复定位分析.并查阅各种资料文章搞懂后,他发现没有文章把这两个队列以及怎么观察他们的指标说清楚. 因此,蛰剑写下这篇文章 ...

  6. Wireshark基本介绍和学习TCP三次握手

    wireshark介绍 wireshark的官方下载网站: http://www.wireshark.org/ wireshark是非常流行的网络封包分析软件,功能十分强大.可以截取各种网络封包,显示 ...

  7. iOS 开发:TCP三次握手连接

    在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握 ...

  8. TCP三次握手四次挥手详解

    转载 http://www.cnblogs.com/zmlctt/p/3690998.html 相对于SOCKET开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不需 ...

  9. TCP三次握手及四次挥手详细 转

    一.TCP报文格式        TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: 图1 TCP报文格式 上图中有几个字段需要重点介绍下:      ...

随机推荐

  1. 移动端开发为什么使用@2x@3x图片

    物理.逻辑与位图像素的概念 关于设备物理像素和逻辑像素,这两个像素一个是实体的,一个是抽象的单位.除此之外还有一个不可忽视的像素,就是位图像素. 物理像素(设备像素):指的是设备屏幕实际拥有的像素点. ...

  2. CentOS7.5环境下Docker基本操作

     1. 查找Docker中Centos镜像文件 docker search centos 2. 下载Docker中Centos镜像文件(默认下载最新版本) docker pull centos 3. ...

  3. SpringBoot整合RabbitMQ-5.7-课堂笔记-02

  4. Discuz!X系列全版本后台sql注入复现

    圈子某位大佬公布的0day,拿来刷一刷,漏洞分析请移步大佬文章.大佬链接 0x01 环境准备 1.首先去码云下载最新版本的discuz(DiscuzX 3.4 R20191201). 2.将upaod ...

  5. Linux 下通过ping判断机器有没有外网。(不用root)

    背景: 想实现一个判断当前系统有没有外网的方法,想到了两种思路: 1)实现一个ICMP协议.但是这个需要root权限才能运行.可以参考:https://www.cnblogs.com/xcywt/p/ ...

  6. 随意写文件命令?怎么向屏幕输出带空格的字符串,比如”hello world”?

    写文件命令:vi 向屏幕输出带空格的字符串:echo hello world

  7. 怎么样把ModelMap里面的数据放入Session里面?

    答:可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key.

  8. JavaScript的一些实用操作(逐步添加)

    1.js代码简洁高效计时 console.time('a'); //记录时间开始 ... console.timeEnd('a'); //记录时间结束 a: 12857.81103515625ms / ...

  9. org.apache.kafka.common.errors.SerializationException: Error deserializing... Caused by: org.apache.kafka.common.errors.SerializationException: Size of data received by IntegerDeserializer is not 4

    原因,最近开发的kafka消息接收,突然报如下错: org.apache.kafka.common.errors.SerializationException: Error deserializing ...

  10. CAS和CAP代表的作用

    CAS(自旋锁):https://www.jianshu.com/p/ab2c8fce878b CAP原则:https://baike.baidu.com/item/CAP原则/5712863?fr= ...