简介

经典的TCP三次握手大家应该很熟悉了,三次握手按道理说应该是最优的方案了,当然这是对于通用的情况来说的。那么在某些特殊的情况下是不是可以提升TCP建立连接的速度呢?

答案是肯定的,这就是今天我们要讲的TCP fast open和netty。

TCP fast open

什么是TCP fast open呢?

TCP fast open也可以简写为TFO,它是TCP协议的一种扩展。为什么是fast open呢?这是因为TFO可以在初始化建立连接的时候就带上部分数据,这样在TCP连接建立之后,可以减少和服务器交互的次数,从而在特定的情况下减少响应的时间。

既然TFO这么好,为什么我们很少见到使用TFO协议的呢?

这是因为TFO是有缺陷的,因为TFO会在sync包中带上一些数据信息,那么当sync包重发的时候,就会造成接收方接受到重复的数据。

所以,如果是用TFO,那么接收方则需要具有能够处理重复数据的能力。

在程序界,防止数据重复提交有一个好听的名字叫做幂等性,只有具有幂等性的服务器才能够使用TFO。

开启TFO

既然TFO这么优秀,怎么才能开启TFO呢?

TFO的开启首先需要操作系统的支持,如果你是mac系统,恭喜你,mac默认情况下已经支持TFO了,你不需要进行任何操作。

如果你是Linux系统,那么需要查看/proc/sys/net/ipv4/tcp_fastopen这个文件。

tcp_fastopen可以有四种值,如下所示:

0 -- 表示TFO未开启

1 -- 表示TFO开启了,但是只对客户端有效

2 -- 表示TFO开启了,但是只对服务器端有效

3 -- 表示TFO开启了,同时对客户端和服务器端有效

通过上面的设置,我们就在操作系统层开启了TFO的支持。

接下来,我们看一下如何在netty中使用TFO。

netty对TFO的支持

首先我们看下如何在netty的服务器端开启TFO支持。

在这之前,我们先回顾一下如何建议一个普通的netty服务器:

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new TFOServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口并开始接收连接
ChannelFuture f = b.bind(port).sync();

上面的代码中,我们看到ServerBootstrap可以设置option参数,ChannelOption中包含了所有可以设置的channel的参数,对应的TFO的参数是ChannelOption.TCP_FASTOPEN, 所以我们只需要添加到ServerBootstrap中即可:

sb.option(ChannelOption.TCP_FASTOPEN, 50)

ChannelOption.TCP_FASTOPEN的值表示的是socket连接中可以处于等待状态的fast-open请求的个数。

对于客户端来说,同样需要进行一些改动,先来看看传统的client端是怎么工作的:

 EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new TFOClientHandler());
}
}); // 连接服务器
ChannelFuture f = b.connect(HOST, PORT).sync();

client要支持TFO,需要添加这样的操作:

b.option(ChannelOption.TCP_FASTOPEN_CONNECT, true)

还记得TFO是做什么的吗?TFO就是在sync包中发送了一些数据。所以我们需要在client端对发送的数据进行处理,也就是说在client和server端建立连接之前就需要向channel中发送消息。

要获得非建立连接的channel,则可以调用Bootstrap的register方法来获取channel:

Channel channel = b.register().sync().channel();

然后向该channel中写入byteBuf:

ByteBuf fastOpenData = directBuffer();
fastOpenData.writeBytes("TFO message".getBytes(StandardCharsets.UTF_8));
channel.write(fastOpenData);

最后再和服务器建立连接:

// 连接服务器
SocketAddress serverAddress = SocketUtils.socketAddress("127.0.0.1", 8000);
ChannelFuture f = channel.connect(serverAddress).sync();

总结

这样一个一个支持TFO的客户端和服务器就完成了。尽情使用吧。

本文的例子可以参考:learn-netty4

本文已收录于 http://www.flydean.com/44-netty-tcp-fast-open/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

netty系列之:让TCP连接快一点,再快一点的更多相关文章

  1. 前端通信:ajax设计方案(八)--- 设计请求池,复用请求,让前端通信快、更快、再快一点

    直接进入主题,本篇文章有点长,包括从设计阶段,到摸索阶段,再到实现阶段,最后全面覆盖测试阶段(包括数据搜集清洗),还有与主流前端通信框架进行对比PK阶段. 首先介绍一下一些概念: 1. 浏览器的并发能 ...

  2. 我为 Netty 贡献源码 | 且看 Netty 如何应对 TCP 连接的正常关闭,异常关闭,半关闭场景

    欢迎关注公众号:bin的技术小屋,本文图片加载不出来的话可查看公众号原文 本系列Netty源码解析文章基于 4.1.56.Final版本 写在前面..... 本文是笔者肉眼盯 Bug 系列的第三弹,前 ...

  3. Netty系列(四)TCP拆包和粘包

    Netty系列(四)TCP拆包和粘包 一.拆包和粘包问题 (1) 一个小的Socket Buffer问题 在基于流的传输里比如 TCP/IP,接收到的数据会先被存储到一个 socket 接收缓冲里.不 ...

  4. TCP系列07—连接管理—6、TCP连接管理的状态机

            经过前面对TCP连接管理的介绍,我们本小节通过TCP连接管理的状态机来总结一下看看TCP连接的状态变化 一.TCP状态机整体状态转换图(截取自第二版TCPIP详解) 二.TCP连接建立 ...

  5. TCP系列05—连接管理—4、TCP连接的ISN、连接建立超时及TCP的长短连接

    一.TCP连接的ISN         之前我们说过初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(di ...

  6. TCP系列03—连接管理—2、TCP连接的同时打开和同时关闭

    在前面的内容中我们介绍了TCP连接管理中最常见的三次握手方式和四次挥手的方式.但是有可能A和B两端同时执行主动打开并连接对方或者同时执行主动关闭连接(尽管发生这种情况的可能性比较低低),这个时候的流程 ...

  7. 支持并发的httpclient(基于tcp连接池以及netty)

    闲来无事,将曾经自己写的一个库放出来吧. . 有的时候会有这样子的需求: (1)serverA通过HTTP协议来訪问serverB (2)serverA可能会并发的像B发送非常多HTTP请求 类似于上 ...

  8. netty系列之:来,手把手教你使用netty搭建一个DNS tcp服务器

    目录 简介 搭建netty服务器 DNS服务器的消息处理 DNS客户端消息请求 总结 简介 在前面的文章中,我们提到了使用netty构建tcp和udp的客户端向已经公布的DNS服务器进行域名请求服务. ...

  9. TCP系列04—连接管理—3、TCP连接的半打开和半关闭

    在前面部分我们我们分别介绍了三次握手.四次挥手.同时打开和同时关闭,TCP连接还有两种场景分别是半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Du ...

随机推荐

  1. 初识python: 生成器

    生成器定义理解,直接上代码: #!/user/bin env python # author:Simple-Sir # time:20181005 # 生成器 ''' # 列表生成式 a=[i for ...

  2. SSM实现支付宝支付

    学习支付宝支付 一.支付宝测试环境代码测试 1.下载电脑网站的官方demo: 下载地址:https://docs.open.alipay.com/270/106291/ 2.下载解压导入eclipse ...

  3. 图形测试分析毫无头绪?HarmonyOS图形栈测试技术帮你解决

    作者:huangran,图形图像技术专家 应用开发以后无法知道性能瓶颈的根因是什么?滑动卡顿.白块产生的原因是什么?代码写完之后,不知道如何优化让它表现地更好-- 我们发现,如今测试人员的需求已经不只 ...

  4. 微软开源Kubernetes服务网格项目Open Service Mesh​

    尽管微服务环境提供可移植性,允许更快更频繁的部署周期,甚至还能让组织创建关注于特定领域的团队,但这也伴随着对于流量管理.安全以及可观测性等需求的增长.在整个生态系统中,针对这些需求的服务网格模式的实现 ...

  5. elementui-日期选择器时间清空报错踩坑

    今天在项目中遇到了这个大坑 具体问题:在日期清空时会报错 解决方法:给日期绑定的值添加监听

  6. 【Java】静态与非静态

    文章目录 静态与非静态 static关键字 使用static修饰属性:静态变量(或类变量) 类变量与实例变量的内存解析 使用static修饰方法:静态方法 使用static的注意点 开发中,如何确定一 ...

  7. C#服务器端使用office组件

    http://www.myexception.cn/asp-dotnet/386522.html 不装office那就把Interop.Excel.dll Interop.Office.dll Int ...

  8. 浅谈MySQL同步到ElasticSearch的几种方式及其优缺点

    同步双写 优点:业务逻辑简单. 缺点: 硬编码,有需要写入mysql的地方都需要添加写入ES的代码: 业务强耦合: 存在双写失败丢数据风险: 性能较差:本来mysql的性能不是很高,再加一个ES,系统 ...

  9. 原子操作atomic解读

    下面从一个问题引入: // ConsoleApplication5.cpp : 定义控制台应用程序的入口点. #include "stdafx.h" #include<ran ...

  10. golang中通过bufio和os包读取终端中输入的一行带空格的数据

    1. 如果读取不带空格的数据可以使用fmt.Scan或fmt.Scanln读取一个或多个值,但是不能读取带空格的数据,可以使用bufio和os两个包结合 package main import ( & ...