专栏首页程序员开发者社区TCP连接建立和释放

TCP连接建立和释放

什么是TCP协议?

TCP 是面向连接的,保证高可靠连性(数据无丢失,数据不错位,数据不乱序,数据无重复)的传输协议。

TCP头

  1. 源端口和目的端口 各占2个字节,分别些人源端口号和目的端口号。
  2. 序号 占4个字节,范围是 【0 - 2^32-1 】 4284967296 个序号。序号增加到 2^32-1 ,下一个序号又回到0 ,序号使用 mod 2^32 运算。也叫做报文段序号。
  3. 确认号 占 4个字节 期望收到对方下一个报文段的第一个数据字节的序号,比如 B 正确收到了 A 发送过来的一个报文段。其报文序号字段值是501,而数据长度是 200 字节 ,(序号501-700),这个表名B正确收到了 A 发送的到序号700为止的数据,B期望收到的下一个序号是701 ,于是 B 再发送给A 的确认报文段中确认号置为 701。
  4. 数据偏移 占4位,指出的是 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远。这个字段其实上也是指出 TCP 报文段的首部长度。 单位是4字节 ,4位能表示最大数是 15 ,首部最大长度即为 15*4字节 = 60 字节。
  5. 紧急 URG 当 URG = 1 时,表示紧急指针字段有效,表示报文段中有紧急数据, 应尽快发送,而不是按照原来的排队顺序发送。场景是,已经发送了一个很长的一个程序,需要远程主机上 运行,由于一些原因,要取消该程序运行,因此用户发送中断命令 Control+C,如果不使用紧急数据,那么这两个字符将存储在TCP的缓存末尾。只有在所有数据发送完毕之后,这两个字符才能交付到接收方程序上,浪费了很多时间。
  6. 确认ACK 仅当 ACK =1 是确认号字段才有效,当 ACK =0 是,确认好无效。TCP 规定,在连接建立后所有传输的报文都必须把 ACK 置1
  7. 推送PSH 当两个应用进程进行交互式通讯是,有时在一端的应用进程希望键入一个命令后立即就能收到对方的响应。在这种情况。TCP 就可以使用推送 push 操作。
  8. 复位 RST 当 RST = 1时,表明 TCP 连接中出现严重的差错(如 由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
  9. 同步 SYN 在连接建立时用来同步序号,当SYN =1 而ACK =0 时,表明这是一个连接请求报文段。对方如果同意建立连接,则应在影响的报文段使用 SYN = 1 和Ack =1 ,因此,SYN 置成 1 表示这是一个连接请求或者连接接受报文。
  10. 终止 FIN 用来释放一个连接,当 FIN = 1 时,表名此报文段的发送方的数据已经发送完毕,并要求释放运输连接。
  11. 窗口 占 2个字节, 窗口是 【0,2^16 -1】之间的整数,窗口指的是发送本报文段的乙方的接收窗口, 窗口值告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量。 为啥要有这个限制,因为接收方的数据缓存空间是有限的。
  12. 校验和 占 2 个字节。校验和字段校验的范围包括首部和数据这两部分。
  13. 紧急指针 占 2个字节 紧急指针金在 URG =1 时才有意义,它指出本报文段的紧急数据的字节数 ,因此紧急指针指出了紧急数据的末尾在报文段中的位置,所有紧急数据都处理完时, TCP 就告诉应用程序恢复到正常操作值。
  14. 选项 长度可变, 最长可达到 40 字节,当没有使用选项时, TCP 首部的长度是 20 字节。

校验和计算

发送时:

1、把校验和字段设置为0;

2、把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和;

3、把得到的结果存入校验和字段中

def carry_around_add(a, b):
    c = a + b
    return (c & 0xffff) + (c >> 16)

def checksum2(msg):
    s = 0
    for i in range(0, len(msg), 2):
        w = (ord(msg[i]) << 8) + ord(msg[i + 1])
        s = carry_around_add(s, w)
    return ~s & 0xffff

接收时

1、把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;

2、检查计算出的校验和的结果是否为0;

3、如果等于0,说明被整除,校验和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。

def checksum(data):  # calculate checksum
    s = 0
    n = len(data) % 2
    for i in range(0, len(data) - n, 2):
        s += ord(data[i]) + (ord(data[i + 1]) << 8)
    if n:
        s += ord(data[i + 1])
    while (s >> 16):
        s = (s & 0xFFFF) + (s >> 16)
    s = ~s & 0xffff
    return s

TCP 可靠传输

接收序号和确认序号,在途中有数据丢失的情况下,返回ACK序号进行重发。

TCP的特点

  • 面向连接的传输层协议
  • 每一条TCP连接只能有两个端点
  • 提供可靠交付的服务
  • 提供全双工通信
  • 面向字节流

建立连接: TCP 三次握手

1. A 向 B 发出连接请求报文段,此时首部 SYN = 1 同时选择一初始序号 seq = x

2. B 接收连接请求报文段后,如果同意连接,则向 A 确认,确认报文段中 SYN 位 和 ACK 位都是 1 ,确认号 ack = x+1,同时也为自己初始一个序号 seq = y

3. A 收到 B的确认后, 还需要给 B 确认,确认报文段的 ACK =1 , 确认号 ack = y+1, 而自己的序号 seq = x+1

通过抓包可以看到三次握手建立连接如下:

断开连接:四次挥手

  1. A 向 B 发送连接释放报文端,并停止发送数据,主动关闭 TCP 连接,报文端首部 FIN 设置成1 ,序号 seq = u ,它等于前面已经传输过来的最后一个自己的序号+1
  2. B 接收连接释放报文后发送确认报文 ,确认号 ack = u+1, 而这个报文段自己的序号是v, 等于B前面已经传送状态的最后一个字节序号+1
  3. A 收到 B的确认信号之后,进入终止等待状态,等待B发送的连接释放报文B 发送连接释放报文,必须重复上次发送的确认号 ack = u+1 ,B 进入最后确认状态 等待 A 确认
  4. A 收到B的连接释放报文后,发送确认 ACK = 1, 确认好 ack = w+1 ,序号 seq = u+1

通过抓包可以看到,断开连接如下:

本文分享自微信公众号 - 程序员开发者社区(gh_016ffe40d550),作者:猿星人

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 可靠消息的最终一致性解决方案

    王小明_HIT
  • 【深入理解Java原理】 JVM 内存区域

    Java 内存区域分成,堆,方法区,虚拟机栈,本地方法栈,程序计数器 (直接内存不是JVM内存的一部分但是有时候会导致OutOFMemory)

    王小明_HIT
  • 国内如何免费访问 Google

    1.下载 Chrome 扩展程序离线安装文件 google-access-helper.zip

    王小明_HIT
  • 位置与标识分离——入向流量优化

    前面聊过了一个数据中心站点内部的连接优化,也聊过了数据中心多个站点间的互联优化,那么还剩下一个问题就是用户如何通过Internet访问数据中心中的服务器/虚拟机...

    SDNLAB
  • 如何使用 Gin 和 Gorm 搭建一个简单的 API 服务 (二)

      这是系列文章的第二篇。下面是另外两篇的链接: 如何使用 Gin 和 Gorm 搭建一个简单的 API 服务(一) 如何使用 Gin 和 Gorm 搭建一...

    用户2443625
  • 《深入浅出Node.js》:Node异步编程解决方案 之 事件发布-订阅模式

    灵活掌握函数式编程,异步编程就有了得心应手的基础。之所以说是基础,是还需要对异步的编程思路有清晰的认识。

    前端_AWhile
  • 线程休眠只会用 Thread.sleep?来,教你新姿势!

    线程休眠是 Java 开发经常会用到的一个手段,就是让当前线程睡一会儿,睡醒之后再继续运行。

    Java技术栈
  • java MS之泛型

    http://blog.csdn.net/stypace/article/details/42102567

    bear_fish
  • Python学习,爬虫不一定非要抓数据,也可以做自己喜欢的应用程序

    最近各种负面消息,对爬虫er来说,并不是很友好,当然这个是对于从业者来说的,对像我这样的正在学习python的个人来说,python爬虫的学习只需要保持以下几点...

    云飞
  • Python学习,爬虫不一定非要抓数据,也可以做自己喜欢的应用程序

    最近各种负面消息,对爬虫er来说,并不是很友好,当然这个是对于从业者来说的,对像我这样的正在学习python的个人来说,python爬虫的学习只需要保持以下几点...

    云飞

扫码关注云+社区

领取腾讯云代金券