TCP 协议

本贴最后更新于 2674 天前,其中的信息可能已经东海扬尘

TCP:可靠传输、按序到达。

一、TCP 报文段格式
源端口号(2byte)、目的端口号(2byte)
序列号(4byte)
ACKnum(4byte)
Offset(4bit)、Reserved(4bit)、TCP Flags(1byte)、Window(2byte)
Checksum(2byte)、...
...

二、三次握手

  1. 客户端向服务器发送连接建立请求报文段(Segement)(SYN=1,seq=x)(调用了 connect()方法),发送之后客户端进入 SYN_SEND 状态;
  2. 服务器收到客户端的请求报文段,向客户端发送一个 ACK 和连接建立请求结合在一起的报文段(ACK=1,ACKnum=x+1,SYN=1,seq=y),并从 LISTEN 状态(调用了 listen()方法)进入 SYN_RCVD 状态;
  3. 客户端收到 ACK 报文段后,向服务器发送一个 ACK 报文段(ACK=1,ACKnum=y+1),并进入 ESTABLISHED 状态;
  4. 服务器收到 ACK 报文段,也进入 ESTABLISHED 状态。
    至此,客户端和服务器的连接建立,之后就可以调用 read()和 write()方法进行读写操作了。

三、四次挥手

  1. 客户端向服务器发送连接关闭请求报文段(FIN=1,seq=x)(调用了 close()方法),发送之后客户端进入 FIN_WAIT_1 状态;
  2. 服务器收到客户端的请求报文段,向客户端发送 ACK 报文段(ACK=1,ACKnum=x+1),并进入 CLOSE_WAIT 状态;
  3. 客户端收到服务器的 ACK 报文段后进入 FIN_WAIT_2 状态;
  4. 服务器向客户端发送连接关闭请求报文段(FIN=1,seq=y)(调用了 close()方法),发送之后服务器进入 LAST_ACK 状态;
  5. 客户端收到服务器的请求报文段,向服务器发送 ACK 报文段(ACK=1,ACKnum=y+1),并进入 TIME_WAIT 状态;
  6. 服务器收到客户端的 ACK 报文段,进入 CLOSE 状态;
  7. 客户端等待 2MSL,期间没有收到服务端的连接关闭请求博爱文段,则进入 CLOSE 状态。
    至此,客户端与服务器的连接关闭。

MSL(Maxinum Segment Live)
TCP 报文在网络传输时最长生存时间。

客户端为什么要等待 2MSL
因为 ACK 报文段可能在网络传输的过程中丢失。如果发送了这种情况,那么服务器在等待 2MSL 时间后会重新一个连接关闭请求报文段,客户端在等待的这 2MSL 时间内正好可以收到这个请求报文段,于是重发 ACK 报文段,再等待 2MSL,重复这个过程直到在等待的 2MSL 时间内没有收到请求报文段,进入 CLOSE 状态。

SYN Flood 攻击
描述:给服务器发了一个 SYN 后,就下线了,于是服务器需要默认等 63s 才会断开连接,这样,攻击者就可以把服务器的 syn 连接的队列耗尽,让正常的连接请求不能处理。
解决方法:Linux 下给了一个叫 tcp_syncookies 的参数来应对这个事——当 SYN 队列满了后,TCP 会通过源地址端口、目标地址端口和时间戳打造出一个特别的 Sequence Number 发回去(又叫 cookie),如果是攻击者则不会有响应,如果是正常连接,则会把这个 SYN Cookie 发回来,然后服务端可以通过 cookie 建连接(即使你不在 SYN 队列中)。

三、确认机制
一种是确认收到的最大的连续收到的包。
一种是收到一个包去人一个包。

四、超时重传机制
一种是重传超时的包及其之后的包(因为接收端只确认了最大的连续收到的包),快,但浪费带宽。
一种是仅重传超时的包,慢,但节省带宽。

往返时间(RTT,Round Trip Time)
通过 RTT+ 算法(好几种)算出超时重传时间(RTO,Retransmission TimeOut)。

五、滑动窗口协议
window:还有多少缓冲区可以用。

发送端
LastByteAcked、LastByteSent、LastByteWriter
SendWindow、UsableWindow

接收器
LastByteRead、NextByteExpected、LastByteRcvd
...、ReceiveWindow
window=MaxRcvBuffer - LastByteRcvd – 1

六、拥塞控制
慢启动阈值(ssthresh,slow start threshold)

拥塞控制算法:
Tahoe:没有快速恢复阶段;
Reno:增加了快速恢复阶段。

1. 慢启动
拥塞窗口(cwnd,Congestion Window)。
①. 连接建立后初始化 cwnd=1;
②. 每当收到一个 ACK,cwnd++,呈线性上升;
③. 每过一个 RTT,cwnd*=2,呈指数上升;
④. 当 cwnd>=慢启动阈值时,将 cwnd 减半,进入拥塞避免算法;

2. 拥塞避免
①. 每收到一个 ACK,cwnd = cwnd + 1/cwnd;
②. 每过一个 RTT,cwnd += 1;

3. 快速重传
收到 3 个重复 ACK 就重传包,然后 cwnd = cwnd /2,ssthresh = cwnd, 进入快速恢复阶段。
(以前是等到超过超时重传时间 RTO 再重传包,然后 ssthresh = cwnd /2,cwnd 置为 1,重新进入慢启动。)

4. 快速恢复
快速恢复阶段认为,还有 3 个重复 ACK 说明网络并不那么糟糕,所以
①. cwnd = ssthresh + 3*MSS;
②. 重传重复 ACK 指定的包;
③. 如果再收到重复 ACK,直接 cwnd += 1;
④. 如果收到新的 ACK,那么 cwnd = ssthresh,然后进入拥塞避免算法。

这个快速恢复算法存在的问题就是它依赖于 3 个重复的 ACK。 注意,3 个重复的 ACK 并不代表只丢了一个数据包,很有可能是丢了好多包。但这个算法只会重传一个,而剩下的那些包只能等到 RTO 超时,于是,进入了恶 梦模式——超时一个窗口就减半一下,多个超时会超成 TCP 的传输速度呈级数下降,而且也不会触发快速恢复算法了。

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 651 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    494 引用 • 928 回帖
  • 倾城之链
    23 引用 • 66 回帖 • 157 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 175 关注
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    124 引用 • 74 回帖
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    6 引用 • 140 回帖
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    729 引用 • 1278 回帖
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    180 引用 • 821 回帖
  • 微信

    腾讯公司 2011 年 1 月 21 日推出的一款手机通讯软件。用户可以通过摇一摇、搜索号码、扫描二维码等添加好友和关注公众平台,同时可以将自己看到的精彩内容分享到微信朋友圈。

    132 引用 • 796 回帖 • 1 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖 • 2 关注
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 32 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 146 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    36 引用 • 155 回帖
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    6 引用 • 15 回帖 • 39 关注
  • OnlyOffice
    4 引用 • 22 关注
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 399 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 45 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 8 关注
  • 外包

    有空闲时间是接外包好呢还是学习好呢?

    26 引用 • 233 回帖
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 1 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 608 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 718 关注
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    157 引用 • 290 回帖
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 7 关注