惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
D
DataBreaches.Net
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog RSS Feed
Recent Announcements
Recent Announcements
The Register - Security
The Register - Security
S
Secure Thoughts
Y
Y Combinator Blog
The Last Watchdog
The Last Watchdog
L
LINUX DO - 最新话题
V2EX - 技术
V2EX - 技术
腾讯CDC
GbyAI
GbyAI
G
Google Developers Blog
博客园 - 司徒正美
博客园 - 三生石上(FineUI控件)
T
The Exploit Database - CXSecurity.com
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
Schneier on Security
Schneier on Security
Microsoft Security Blog
Microsoft Security Blog
Jina AI
Jina AI
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
MyScale Blog
MyScale Blog
Help Net Security
Help Net Security
K
Kaspersky official blog
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
AI
AI
MongoDB | Blog
MongoDB | Blog
Scott Helme
Scott Helme
J
Java Code Geeks
Engineering at Meta
Engineering at Meta
H
Heimdal Security Blog
H
Help Net Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
云风的 BLOG
云风的 BLOG
Microsoft Azure Blog
Microsoft Azure Blog
S
Security Affairs
TaoSecurity Blog
TaoSecurity Blog
The GitHub Blog
The GitHub Blog
Hacker News: Ask HN
Hacker News: Ask HN
Martin Fowler
Martin Fowler
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Project Zero
Project Zero
T
The Blog of Author Tim Ferriss
Last Week in AI
Last Week in AI

Java技术经验分享

生产故障处理SOP分享 | Java技术经验分享 系统稳定性建设实践总结【转载】 | Java技术经验分享 valine访问leancloud国际版异常,评论失效修复 | Java技术经验分享 匆匆忙忙的2021 | Java技术经验分享 聊一下换工作 | Java技术经验分享 IoT系列(2):WIFI设备常见配网方案介绍 | Java技术经验分享 IoT系列(1):什么是物联网 | Java技术经验分享 Java8特性2 - StreamApi | Java技术经验分享 Java8特性1 - lambda表达式&函数式接口 | Java技术经验分享 设计模式(5)-适配器模式 | Java技术经验分享 设计模式(4)-建造者模式 | Java技术经验分享 设计模式(3)-原型模式与浅拷贝和深拷贝 | Java技术经验分享 设计模式(2)-工厂模式图文介绍 | Java技术经验分享 设计模式(1)-带你了解3类8种单例模式 | Java技术经验分享 Java时间处理5---Java8中时区相关类库介绍 | Java技术经验分享 Java时间处理4---Java8中LocalDate、LocalTime、LocalDateTime介绍 | Java技术经验分享 Java时间处理3---Java8中Instant、Duration、Period、Clock介绍 | Java技术经验分享 一些有意思的问答 | Java技术经验分享 Nacos系列博客说明 | Java技术经验分享 菜鸡程序员的2019年度总结 | Java技术经验分享 Java中“附近的人”实现方案讨论及代码实现 | Java技术经验分享 Java时间处理2----时区TimeZone类方法探究(Java8以前) | Java技术经验分享 Java时间处理1----Date和Calendar方法探究(Java8以前) | Java技术经验分享 FastJson中JSONString、JavaBean、JSONObject、JSONArray的转换关系及API示例 | Java技术经验分享 2019.11软考软件设计师归来心得体会及复习备考指南 | Java技术经验分享 你还没用过“约定式提交”吗?那你赶紧来补补知识吧 | Java技术经验分享 教你如何看懂UML中的类图及类图中的关系 | Java技术经验分享 设计模式总览 | Java技术经验分享 萌新入门Github请看这里,学不会远程教 | Java技术经验分享 Hexo的工作原理探究 | Java技术经验分享 Hexo-theme-butterfly修改调整记录教程 | Java技术经验分享 排序8:基数排序 | Java技术经验分享 排序7:归并排序 | Java技术经验分享 排序6:快速排序 | Java技术经验分享 排序5:冒泡排序 | Java技术经验分享 排序4:堆排序 | Java技术经验分享 排序3:选择排序 | Java技术经验分享 排序2:希尔排序 | Java技术经验分享 排序1:直接插入排序 | Java技术经验分享 推荐一款博客一文多发的良心工具OpenWrite | Java技术经验分享 近期学习计划 | Java技术经验分享 Nacos(九):Nacos集群部署和遇到的问题 | Java技术经验分享 Nacos(八):Nacos持久化 | Java技术经验分享 Nacos(七):Nacos共享配置 | Java技术经验分享 Nacos(六):多环境下如何“管理”及“隔离”配置和服务 | Java技术经验分享 Nacos(五):多环境下如何“读取”Nacos中相应的配置 | Java技术经验分享 Nacos(四):SpringCloud项目中接入Nacos作为配置中心 | Java技术经验分享 Nacos(三):Nacos与OpenFeign的对接使用 | Java技术经验分享 Nacos(二):SpringCloud项目中接入Nacos作为注册中心 | Java技术经验分享 Nacos(一):Nacos介绍 | Java技术经验分享 20190719小组分享 | Java技术经验分享 Java中equals和HashCode方法的分析 | Java技术经验分享 Java中==和equals方法的分析 | Java技术经验分享 Java中的自动拆装箱、装箱缓存 | Java技术经验分享 About-blog | Java技术经验分享 Java中的编译、反编译和反编译工具全家桶分享 | Java技术经验分享 finalize()的生命周期(执行过程) | Java技术经验分享 Java关键字之final、finally与finalize方法 | Java技术经验分享 Java中重写、重载 | Java技术经验分享 Java中面向对象的三大特征:继承、封装、多态 | Java技术经验分享 DockerFile介绍 | Java技术经验分享 Docker环境下安装Gitlab | Java技术经验分享 Docker中私有仓库的搭建流程 | Java技术经验分享 Centos7下两种方式安装Docker-CE | Java技术经验分享 Vert.x创建一个Http服务 | Java技术经验分享 Vert.x Core(二)- Event Bus(事件总线) | Java技术经验分享 Vert.x-Core(一)- 基础篇 | Java技术经验分享 SpringBoot项目中实现国际化 | Java技术经验分享 Vert.x介绍 | Java技术经验分享 毕设选题项目本地运行环境搭建教程 | Java技术经验分享 Jupyter Notebooks的安装和使用介绍 | Java技术经验分享 算法笔试题:1元,5元,10元,20元,50元、100元面值人民币组合给定x元的问题 | Java技术经验分享 Quartz学习总结 | Java技术经验分享 SpringBoot2.x集成Redis | Java技术经验分享 SpringBoot2.x集成MongoDB | Java技术经验分享 [SpringCloud学习] - 浅谈微服务架构 | Java技术经验分享 基于hexo和coding免费搭建个人博客网站 | Java技术经验分享 Hello World | Java技术经验分享
Vert.x创建TCP服务端及客户端 | Java技术经验分享
文章作者: LarsCheng · 2019-04-02 · via Java技术经验分享
本文是我在学习Vert.x过程中的一些笔记,作为记录。
因为是初学,对Vert.x的理解还不够透彻,如有错误之处我们可以在评论中一起讨论呦。

环境准备

  • JDK8+
  • Maven
  • IDE
  • Vert.x 3.6.3

我们通常用到的最多的应该是Http服务,创建一个Http服务端似乎web开发中常有的事情。但是如果有一个需要Tcp服务的场景,这时候我们会想到Socket编程,基于Socket实现一个Tcp服务的过程是及其考验编程水平的,需要手动处理网络和线程问题。于是乎我们又想到了Netty,用Netty来实现Tcp服务似乎也不错啊,他简化了传统的Nio操作,但是如果没有接触过Netty则需要从头学习,学习成本较高。其实我们可以使用Vertx来创建Tcp服务,因为Vert.x本来就是基于Netty的,而且通过Vertx创建Tcp服务非常方便。

vertx中创建Tcp服务端

默认的创建方式如下:

NetServer netServer = vertx.createNetServer();

默认创建的Tcp服务端实际上是初始化了一个默认的NetServerOptions实例,Tcp服务端会随机选择一个本地未被占用的端口进行监听

当然我们也可以通过配置自定义属性来创建:

NetServer netServer = vertx.createNetServer(new NetServerOptions().setPort(9981));
//可以获取监听的端口
netServer.actualPort();

当创建Tcp服务端监听某一端口时我们注册一个处理器,当创建成功并开始监听时触发:

1
2
3
4
5
6
7
8
//监听指定主机和端口,并且在监听开始时触发通知
vertx.createNetServer().listen(9983, "localhost", res -> {
if (res.succeeded()) {
System.out.println("Tcp服务端启动成功");
} else {
System.err.println("Tcp服务端启动失败");
}
});

当服务端创建成功后,有客户端请求进来,会触发相应的处理器,可以通过connectHandler方法绑定处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//绑定处理器,当有请求进入时触发
NetServer netServer = vertx.createNetServer().connectHandler(netSocket -> {
//得到NetSocket实例
netSocket.handler(buffer -> {
//读取数据
System.out.println("读取到数据:" + buffer.toString() + " 长度为: " + buffer.length());
});

netSocket.write(Buffer.buffer("数据已接收......"), ar -> {
if (ar.succeeded()) {
System.out.println("写入数据成功!");
} else {
System.err.println("写入数据失败!");
}
});
netSocket.closeHandler(ar -> {
System.out.println("客户端退出连接");
});
}).listen(9984, "localhost");

Tcp客户端创建

客户端的创建方式与服务端类似,也有默认的创建方法和自定义的属性配置

1
2
3
4
5
//默认客户端创建
NetClient netClient1 = vertx.createNetClient();

//自定义属性创建
NetClient netClient2 = vertx.createNetClient(new NetClientOptions().setConnectTimeout(10000));

创建Tcp客户端需要使用connect方法连接到服务端后,才可以进行数据的收发

1
2
3
4
5
6
7
8
NetClient client = vertx.createNetClient(new NetClientOptions().setConnectTimeout(10000));
client.connect(9984, "localhost", res -> {
if (res.succeeded()) {
System.out.println("连接成功!");
} else {
System.out.println("连接失败: " + res.cause().getMessage());
}
});

关闭Tcp连接

当请求结束时,可以调用close关闭服务端或者客户端

1
2
3
4
5
6
7
8
9
10
11
12

//1.直接关闭
netServer.close();

//2.关闭结果打印通知
netServer.close(res -> {
if (res.succeeded()) {
System.out.println("关闭成功!");
} else {
System.err.println("关闭失败!");
}
});

项目创建

在IDEA中创建一个Maven工程,pom文件引入Vertx-core的依赖

1
2
3
4
5
6

<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>3.6.3</version>
</dependency>

创建NetServerDemo.java文件,创建并部署Tcp服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.zhengql.www;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetServerOptions;

/**
* 描述: tcp
*
* @author zhengql
* @date 2019/4/2 14:57
*/
public class NetServerDemo extends AbstractVerticle {

public static void main(String[] args) {
Vertx.vertx().deployVerticle(new NetServerDemo());
}




@Override
public void start() throws Exception {

//绑定处理器,当有请求进入时触发
NetServer netServer = vertx.createNetServer().connectHandler(netSocket -> {
//得到NetSocket实例
netSocket.handler(buffer -> {
//读取数据
System.out.println("读取到数据:" + buffer.toString() + " 长度为: " + buffer.length());
});

netSocket.write(Buffer.buffer("数据已接收......"), ar -> {
if (ar.succeeded()) {
System.out.println("写入数据成功!");
} else {
System.err.println("写入数据失败!");
}
});
netSocket.closeHandler(ar -> {
System.out.println("客户端退出连接");
});
}).listen(9984, "localhost", res -> {
if (res.succeeded()) {
System.out.println("Tcp服务端启动成功");
} else {
System.err.println("Tcp服务端启动失败");
}
});
}
}

创建NetClientDemo.java文件,创建并部署Tcp客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.zhengql.www;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetClientOptions;
import io.vertx.core.net.NetSocket;

/**
* 描述:
* Tcp客户端
*
* @author zhengql
* @date 2019/4/2 15:39
*/
public class NetClientDemo extends AbstractVerticle {
public static void main(String[] args) {
Vertx.vertx().deployVerticle(new NetClientDemo());
}




@Override
public void start() throws Exception {


//创建连接到指定主机和端口的客户端,并绑定创建结果的处理器
NetClient netClient3 = vertx.createNetClient(new NetClientOptions().setConnectTimeout(10000))
.connect(9984, "localhost", res -> {
if (res.succeeded()) {
System.out.println("连接成功!");
NetSocket socket = res.result();
//向服务器写入数据
socket.write(Buffer.buffer("发送数据......"), ar -> {
if (ar.succeeded()) {
System.out.println("数据发送成功!");
} else {
System.err.println("数据发送失败!");
}
});

//读取服务端返回的数据
socket.handler(buffer -> {
System.out.println("读取到数据:" + buffer.toString() + " 长度为: " + buffer.length());
});
socket.closeHandler(ar -> {
System.out.println("客户端断开连接");
});
} else {
System.out.println("连接失败!: " + res.cause().getMessage());
}
});
}
}

到此,服务端和客户端的代码已经编写完成

启动NetServerDemo,可以看到控制台中的日志打印如下:

在启动NetClientDemo,控制台打印如下:

客户端启动成功后,此时服务端的日志如下:

上面的代码创建了一个Tcp服务端和Tcp客户端,服务端监听本地的9984端口,客户端与本地的9984端口的Tcp服务端建立连接后发送数据,
当接收到客户端的请求时打印其传来的消息“发送数据......”,并回复“数据已接收......”

至此,一个基于Vert.x的Tcp服务端、客户端创建demo就完成了,是不是比Socket编程要简单很多呢?

资料参考

https://vertx.io/docs/

https://vertx.io/docs/vertx-core/java/