文档章节

【NIO系列】——之TCP探秘

wier
 wier
发布于 06/26 08:46
字数 3312
阅读 3390
收藏 164
点赞 31
评论 9

很开心,上半年发布的spring boot 2中,默认的web 容器是netty ,这说明“反应式” 容器已经是大势所趋,无论是go 语言的协从线程,还是java 基于reactor 线程模型,都是基于事件编程实现高并发的实例。这周开始我会讲关于NiO的一切,底层原理是什么,应用架构有哪些,如何利用其优势构建高性能服务器,欢迎关注。

在介绍NIO之前有必要了解下TCP协议,因为目前多数应用都是给予应用层进行操作,导致隐藏了大量的网路细节,知道这些细节以及原理对我们的问题排查很有益处。

一、TCP 特性

TCP 是一种面向连接的协议,它给用户进程提供可靠的全双工的字节流。确保数据包的可靠,有序,以及支持流量控制。关于TCP 为何要做这些,我们从以下几个方面入手:

  1. IP网络层为何不保证数据包的可靠性

  2. TCP协议如何保证包可达、有序

  3. TCP协议如何支持流量控制

  4. TCP几种状态以及应用

二、IP网络层为何不保证数据包的可靠性

我们先看下OSI的网络分层,在以下分层中,TCP 位于传输层,它保证的是协议的可靠性和连续性。具体的收发报是有底层的链路层以及物理层所决定的,所以TCP 所做的工作,也是基于底层的优化和改进。

客户端与服务器之间的通信使用应用协议,传输层的通信采用TCP协议,而TCP 协议又采用了更低的一层IP协议,IP则使用某种形式的数据链路层通信。

我们知道网络的中的数据,最终通过多个路由器连接传送的。最底层的以太网协议规定了电子信号如何组成数据包,解决了局域网的点对点通信问题,但无法解决多个局域网的的互通问题。

而网络层采用的IP协议,就是定义了一套自己的地址规则,主要解决寻址和路由的功能,根据对方的IP地址,寻找最佳路径传输信息。局域网通过路由器连接,路由器基于IP协议,指导数据包向某个路由借口转发。但IP协议不保证包一定到达以及完整性,特别是网络拥堵的时候,会丢弃一些数据包,保证数据的传送效率。

而保证数据包的完整、有序以及可靠,这就是TCP 协议要来做的事情了。

三、TCP 协议

1、TCP 包组成

很多网络有一个最大传送单元,它是链路层中的网络对数据帧的一个限制,以以太网为例,MTU为1500个字节。一个IP数据报在以太网中 传输,如果它的长度大于该MTU值,就要进行分片传输,使得每片数据报的长度小于MTU。

另外一个数据包还包含头信息,除了自己的Tcp包头,还有IP 头信息和以太网头信息。IP 数据包在以太网数据包的负载里面,最少需要20字节,所以 IP 数据包的负载最多为1480字节。

 

那么tcp的一个包大小是多少呐?

我们需要机遇MSS这个值来确定,MSS是TCP里的一个概念(首部的选项字段中)。MSS是TCP数据包每次能够传输的最大数据分段,TCP报文段的长度大于MSS时,要进行分段传输。 如果不设置,则MSS的默认值就为536个字节 。也就是说一个tcp包的在500字节左右。

 

2、如何保证可靠性

上述也说了,底层的路由转发包,并不保证包的可靠性以及有序性。

首先为了保证包的完整性,TCP 会基于MSS 为大于 MSS的包进行分包处理,默认MSS大小为563byte,其大小小于MUT,以防止在网络层被分片处理。

其次增加SEQ和ACK,同时采用超时重发的机制来保证包的可靠性。

 

1)SEQ

为了保证有序性,TCP 为每个包编配一个Sequence number ,简称 SEQ 。以便接收的一方按照顺序还原。万一发生丢包,也可以知道丢失的是哪一个包。一般第一个包的编号是一个随机数,也可以从1开始。

2)ACK

那么有编号了,如何确保包一定到达?

基于ACK 进行确认。对于接收方来说,每次接受一个包必须返回ack信息,发送端从而确认这个包已经传送到。另外,接收方要对每一条报文做校验。如果校验发现出错,则不发送确认报文,从而触发发送方超时重传。

ACK 包含以下信息:

  • 期待要收到下一个数据包的编号 next SEQ

  • 接收方的接收窗口的剩余容量

 

我们采用wiershark抓包一个oschina的包看下三次握手的数据。

我的本机ip:192.168.1.103
oschinaIp:116.211.174.177
三次握手过程:
1.me->osChina:syn=1 seq=x ack=0
2.osChina->me:syn=1 seq=y ack=x+1
3.me->osChina:seq=x+1 ack=y+1

 

1、me->osChina:syn=1 seq=0 ack=0

2、osChina->me:syn=1 seq=0 ack=0+1

 

3、me->osChina:seq=0+1 ack=0+1

 

对比一下三次握手的过程。

 

3)超时重传

我们知道网络极其不稳定,数据包即便增加了SEQ和ACK,能够保证其有序性,但依然保证丢包或者超时的问题。如果发送端发送数据,或者接收端回复ACK的消息在网络中丢失或者超时怎么处理?

RTO ,超时重传时间。要知道包是否出现超时,需要有一个评估方式,而RTT是对一个给定连接的往返时间的测量。由于网络流量的变化,这个时间会相应地发生改变,TCP需要跟踪这些变化并动态调整超时时间RTO。

发送方如果一定时间内没收到报文的ACK,就认为该报文丢失在网络中了,自动重发该报文。这种机制称之为超时重传。

在这期间,如果接收端的消息,由于丢失,接收端没有收到ack 消息,发送端会向接收端重发这个包。如果因为超时原因,发送端在超时定时器之后收到了这个包的ack 信息,而且发送端已经重复发送了这个消息,此时发送端不会处理,直接丢弃该ack 。而接收端接收到了之后会再次回复ack 信息。

 

四、流量控制

上述中我们知道了TCP协议可以保证数据的可靠性,但是也得兼顾效率。兼顾效率的话需要考虑以下三个方面:

  1. 支持批量发包

  2. 能够基于网络的状况,支持拥堵控制

  3. 能够了解接收端的状况,防止接收端处理不过来

基于以上三个需求,做了以下处理。

 

1、滑动窗口

如果TCP 中的包,都需要发送一个确认一个的话,效率太低了,单次发送和确认一个包,虽然保证了可靠性,但无法保证其效率。此时需要一个批量发送和确认的方式,这就是滑动窗口所做的事情。

发送滑动窗口:

发送窗口从左向右移动在这个发送窗口之前的数据必然是已经发送而且得到接收方确认的数据落在发送窗口之内的数据是发送方可以发送的数据在发送窗口之后的数据是不能发送的数据。

 

如果发生超时或者丢失现象。那么有两种解决方案:

1、回退N,丢失的包号之后所有包都重发2、选择重传ARQ,只发丢失的,避免重复的(效率高,防止发送重复的)

 

滑动窗口还有一个作用是让发送端知道接收端的处理状况。假设TCP接收方的缓存已经满了,无法处理更多的,而发送方并不知道,每次会给对方告知当前滑动窗口的大小值 ,此时发送端就不会再发送数据了。

  1. 接收方接收到数据同样马上发送确认,但是同时对发送方宣布窗口大小为0。这样发送方就暂时不会发送数据。

  2. 报文到达时不马上发送确认,直到缓存有足够的空间。这样就可以避免发送方滑动窗口。但是这也存在一个问题,接收方延迟发送确认的时间不应该超过超时时间,如果过长会导致发送方误以为数据丢失重新发送数据。

 

2、拥堵控制

我们知道网络状况有好友坏,好的时候,可以多发些包,坏的时候,如果发包速率不变的话,除了会加重网路负担以外,还会造成包的过多丢失,除非更多的超时重发,这无疑识降低了通信效率。

基于此,TCP通信双方维护一个叫做拥塞窗口(cwnd,congesion window)的值,这个值取决于网络中的拥塞率,发送方的发送窗口的值就等于拥塞窗口的大小。只要网络中没有出现拥塞,拥塞窗口的值就可以增大一些,这样发送方可以发送到网络中的数据就多一些。反之,拥塞窗口的值就减小,从而避免加剧网络的拥塞率。

TCP目前拥塞控制主要有以下4种算法:

  1. 慢启动

  2. 拥塞避免

  3. 快速重传

  4. 快恢复

具体的算法实现方式就不再介绍了,大概实现的功能就是,基于当前的网络状况,找到一个合适的发送速率,防止给网络造成过大的负担。比如说慢启动,就是开始的时候,发送得较慢,然后根据丢包的情况,调整速率:如果不丢包,就加快发送速度;如果丢包,就降低发送速度。

五、TCP 状态

了解TCP的都知道,TCP 建立连接的时候,有三次握手,断开链接的时候又四次握手交互。那么其中的状态是有哪些?

上面的图看着是不是太乱记不住,我们看看下面这张梳理一下,看看具体应用状态。

从上面可以看到,连接建立成功的时候,其状态是ESTABLISHED 的。当接受端的状态为SYN—RECV的时候,表示接受端,已经回复第二次握手信息了,等待发送端再次确认。如果网络中遭受到大量的SYN 攻击,会存在大量的SYN_RECV 状态。此时可以定位这些问题IP ,通过防火墙过滤就能解决大量的假连接问题。

 

六、消失的连接——TIME_WAIT

在网络中,某一端主动关闭而没有通过四次握手关闭,此时tcp已经建立的通道是否还在,多久会关闭?此时的TCP 状态为TIME_WAIT ,可以想象,现实中经常出现这种状况,多数的关闭连接都是主动关闭而非通过协商通信关闭。那么此时关闭,若果再重连还能重连上之前的tcp 通道么,还是需要重现创建。

任何TCP实现必须为MSL选择一个值,默认是2分钟或者30秒,TIME_WAIT默认是2倍的MSL,持续时间在1-4分钟之间。MSL是IP数据包能在网络中存活的最长时间。

TIME_WAIT 存在的两个理由: 1、可靠的实现TCP全双工连接的终止 2、允许老的重复分节在网络中消失

TCP必须防止某个连接的老的重复分组在该连接已经终止后再现,从而被误解成属于同一连接的化身,有time_wait 足够长,是2倍的MSL的,那么足够让某个方向上的分组最多存活MSL秒就被丢弃。

从TIME_WAIT状态到CLOSED状态,有一个超时设置,这个超时设置是 2*MSL(RFC793定义了MSL为2分钟,Linux设置成了30s),如此超过了这个时间,当前的tcp通道就会被定义为关闭。

 

 

更多架构知识,欢迎关注我的公众号,大码候(cool_wier)

© 著作权归作者所有

共有 人打赏支持
wier
粉丝 716
博文 49
码字总数 131483
作品 0
东城
技术主管
加载中

评论(9)

itfanr
itfanr
我的本机ip:192.168.1.103
oschinaIp:116.211.174.177
三次握手过程:
1.me->osChina:syn=1 seq=x ack=0
2.osChina->me:syn=1 seq=y ack=x+1
3.me->osChina:seq=x+1 ack=y+1

总结得好
itfanr
itfanr
MUT 写错了吧
wier
wier

引用来自“kentxp”的评论

spring boot 2中,默认的web 容器是jetty吧
WebFlux,默认情况下,Spring Boot 2使用Netty WebFlux
N
NoComments
必须收藏
kentxp
kentxp
spring boot 2中,默认的web 容器是jetty吧
我是龙的传人
我是龙的传人
干货呀
xiaoaiwhc1
xiaoaiwhc1
这个可以收藏!
talent-tan
talent-tan
给作者点赞
爱吃大肉包
爱吃大肉包
总结的不错。 /uuuu
【NIO系列】——之Reactor模型

在开篇之前,我们对JavaNIO 的使用方式不做过多介绍,这种API的介绍方式网上太多了,没必要详细介绍,我们假设NIO的使用方式,你能够熟练运用。这是NIO系列第三篇: 【NIO系列】——之TCP探秘...

wier
07/11
0
2
互联网技术栈 『Contents Catalog』

image.png 编程语言 Java书单——由入门到上天 UML-类间关系 Java解读-ThreadLocal详解与应用 并发编程-Concurrent用户指南 Java并发编程-原子性变量 Java 并发工具包-常用线程池 基于事件驱...

高广超
2017/11/03
0
0
掘金翻译计划线下活动 — 第一期

掘金翻译计划 Star 马上破一万了,大家快去 Star,一起见证这个伟大时刻 🥇 掘金翻译计划线下见面会来啦,本次活动为翻译计划第一期线下活动,主题是“探秘掘金,探秘翻译计划”。本次活动...

LeviDing
2017/11/13
0
0
小牛电动的软文列表,和实际用户的反馈实在是天上地下。。

搜狐汽车: 《个人电动交通工具通勤日记—小牛 N1 电动踏板车》 http://auto.sohu.com/20150903/n420358519.shtml 光明网IT讯(记者 伍月明) 探秘小牛电动车:80%部件自产 注重更新迭代 ht...

junanhonglei
2015/09/04
104
0
Linuxer-"Linux开发者自己的媒体"第五月稿件和赠书名单

Linuxer已经从一个单纯的读者服务公众号转变为一个为广大用户解决linux学习,工作以及职业生涯实际问题的平台。用户参与,才能让这个平台更加实用,有效。Linuxer平台号召各路大虾一起来建设...

jus3ve
2017/12/20
0
0
探秘IntelliJ IDEA 13测试版新功能——调试器显示本地变量

IntelliJ IDEA在业界被公认为最好的Java开发平台之一,JetBrains公司将在12月正式发布IntelliJ IDEA 13版本。 现在,小编将和大家一起探秘密IntelliJ IDEA 13测试版本新功能——调试器显示本...

kouxunli1
2013/10/23
0
2
OSChina 技术周刊第十六期 —— 每周技术精粹

每周技术抢先看,总有你想要的! 移动开发 【博客】[Android] AS 中 Gradle 配置运行浅析 服务端开发/管理 【软件】安全的即时聊天系统 Tox 【软件】HTTP 代理服务 gopee 【软件】流媒体平台...

OSC编辑部
2015/01/04
2.1K
1
探秘双“11”征服马云刘强东的电商架构 !

在刚刚过去的“双11”,阿里巴巴和京东两大巨头双双创造新的购物纪录:阿里巴巴天猫全天成交额达1682亿元,打破去年1207亿元的纪录;京东全天下单金额超1271亿元,同比增长超过50%。 双11异常...

Lunaqi
2017/11/15
0
0
攻城狮修炼秘籍

漫漫校园生活,孜孜不倦的你,今天书多读一点! 把自己投入知识的海洋吧!为即将成为一名高冷俊俏的程序猿和媛而吹响最后的号角: 各类秘籍自助区 一、测试攻城狮 《软件测试》 《测试之道》...

SVD
2016/09/10
25
0
2017天猫双11,1682亿背后的阿里绝密50+技术

摘要:2017天猫双11, 交易峰值32.5万/秒,支付峰值25.6万/秒,数据库处理峰值,4200万次/秒。1682亿数字的背后是50+神秘技术,让我们在阿里云上与所有新技术相遇! 2017天猫双11的交易额定...

云栖社区
2017/11/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

shell中的函数、shell中的数组、告警系统需求分析

shell中的函数 格式: 格式: function f_name() { command } 函数必须要放在最前面 示例1(用来打印参数) 示例2(用于定义加法) 示例3(用于显示IP) shell中的数组 shell中的数组1 定义数...

Zhouliang6
今天
2
0
用 Scikit-Learn 和 Pandas 学习线性回归

      对于想深入了解线性回归的童鞋,这里给出一个完整的例子,详细学完这个例子,对用scikit-learn来运行线性回归,评估模型不会有什么问题了。 1. 获取数据,定义问题     没有...

wangxuwei
今天
1
0
MAC安装MAVEN

一:下载maven压缩包(Zip或tar可选),解压压缩包 二:打开终端输入:vim ~/.bash_profile(如果找不到该文件新建一个:touch ./bash_profile) 三:输入i 四:输入maven环境变量配置 MAVEN_HO...

WALK_MAN
今天
0
0
33.iptables备份与恢复 firewalld的9个zone以及操作 service的操作

10.19 iptables规则备份和恢复 10.20 firewalld的9个zone 10.21 firewalld关于zone的操作 10.22 firewalld关于service的操作 10.19 iptables规则备份和恢复: ~1. 保存和备份iptables规则 ~2...

王鑫linux
今天
2
0
大数据教程(2.11):keeperalived+nginx高可用集群搭建教程

上一章节博主为大家介绍了目前大型互联网项目的系统架构体系,相信大家应该注意到其中很重要的一块知识nginx技术,在本节博主将为大家分享nginx的相关技术以及配置过程。 一、nginx相关概念 ...

em_aaron
今天
1
0
Apache Directory Studio连接Weblogic内置LDAP

OBIEE默认使用Weblogic内置LDAP管理用户及组。 要整理已存在的用户及组,此前办法是导出安全数据,文本编辑器打开认证文件,使用正则表达式获取用户及组的信息。 后来想到直接用Apache Dire...

wffger
今天
2
0
HFS

FS,它是一种上传文件的软件。 专为个人用户所设计的 HTTP 档案系统 - Http File Server,如果您觉得架设 FTP Server 太麻烦,那么这个软件可以提供您更方便的档案传输系统,下载后无须安装,...

garkey
今天
1
0
Java IO类库之BufferedInputStream

一、BufferedInputStream介绍 /** * A <code>BufferedInputStream</code> adds * functionality to another input stream-namely, * the ability to buffer the input and to * sup......

老韭菜
今天
0
0
STM 32 窗口看门狗

http://bbs.elecfans.com/jishu_805708_1_1.html https://blog.csdn.net/a1985831055/article/details/77404131...

whoisliang
昨天
1
0
Dubbo解析(六)-服务调用

当dubbo消费方和提供方都发布和引用完成后,第四步就是消费方调用提供方。 还是以dubbo的DemoService举例 -- 提供方<dubbo:application name="demo-provider"/><dubbo:registry address="z...

青离
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部