netty2 案例:数据通信
在实际的项目中应该如何使用netty去通信呢?
一般来说,会有以下三种情况,
1长连接 也就是服务器和客户端的通道一直不关闭,如果服务器性能非常好,并且在客户端数量不是很多的情况下,可以选择使用这种方式。
2短连接 一次性批量提交数据,我们可能会吧我们的数据保存在数据库中,比如1个小时提交提交一次。这种做法的弊端是不能够实时传输,实时性要求不高的情况可以推荐使用
3一种特殊的长连接 在特定时间的内,如果服务器和客服端没有通讯 就断开连接 下次当客户端需要再次发送数据的时候,再次连接 。但是这种方式我们需要考虑?
1连接超时以后我们如何断开连接? 而在需要发送数据的时候我们怎么再次连接?
2服务器宕机了怎么办?
1连接超时以后我们如何断开连接?(在netty中可以通过ReadTimeoutHandler类实现超过多长时间断开连接)
而在需要发送数据的时候我们怎么再次连接?
(我们可以封装一个方法 调用该方法就可以获得连接)
2服务器宕机了怎么办?
生产环境我们一般会部署netty集群,结合zookeeper完成。
下面我用代码演示一下
Server端口变化不大 ,主要是客户端
Server端代码
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler; public class Server {
public static void main(String[] args) throws Exception {
//
EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup(); ServerBootstrap bootStrap = new ServerBootstrap(); bootStrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel sc) throws Exception {
// ByteBuf delimiters = Unpooled.copiedBuffer("$".getBytes()) ;
// sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiters ));
// sc.pipeline().addLast(new StringDecoder());
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
sc.pipeline().addLast(new ReadTimeoutHandler(5));//超时时间设置
sc.pipeline().addLast(new ServerHandler());
}
});
ChannelFuture f = bootStrap.bind(8888).sync();
ChannelFuture f1 = bootStrap.bind(9999).sync();
//服务器一直不关闭
f.channel().closeFuture().sync();
f1.channel().closeFuture().sync();
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
} }
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; public class ServerHandler extends ChannelHandlerAdapter { @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("server " + msg);
Data data = new Data();
data.setId(1);
data.setName("server replay");
// 写操作完成以后就断开连接
ctx.writeAndFlush(data).addListener(ChannelFutureListener.CLOSE); } @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
} }
序列化工具代码 这里使用jboss的Marshalling
import io.netty.handler.codec.marshalling.DefaultMarshallerProvider;
import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallingDecoder;
import io.netty.handler.codec.marshalling.MarshallingEncoder;
import io.netty.handler.codec.marshalling.UnmarshallerProvider; import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration; public final class MarshallingCodeCFactory { public static MarshallingDecoder buildMarshallingDecoder() {
//首先通过Marshalling工具类的精通方法获取Marshalling实例对象 参数serial标识创建的是java序列化工厂对象。
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
//创建了MarshallingConfiguration对象,配置了版本号为5
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
//根据marshallerFactory和configuration创建provider
UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);
//构建Netty的MarshallingDecoder对象,俩个参数分别为provider和单个消息序列化后的最大长度
MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024);
return decoder;
} public static MarshallingEncoder buildMarshallingEncoder() {
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);
//构建Netty的MarshallingEncoder对象,MarshallingEncoder用于实现序列化接口的POJO对象序列化为二进制数组
MarshallingEncoder encoder = new MarshallingEncoder(provider);
return encoder;
}
}
================
一个简单的实体类 (Data)
import java.io.Serializable; public class Data implements Serializable{
/**
*
*/
private static final long serialVersionUID = -963211196207628767L;
private Integer id;
private String name; @Override
public String toString() {
return " [id=" + id + ", name=" + name + "]";
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }
==================================================================================================
以下是客户端代码
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler; public class Client {
EventLoopGroup workGroup = null;
Bootstrap bootstrap = null;
ChannelFuture channelFuture = null; private static class ClientFactory {
private static Client instance = new Client();
} public static Client getClientInstance() {
return ClientFactory.instance;
} private Client() {
// 数理化相关对象
workGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(workGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel sc) throws Exception {
// ByteBuf delimiters = Unpooled.copiedBuffer("$".getBytes()) ;
// sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,
// delimiters ));
// sc.pipeline().addLast(new StringDecoder());
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
sc.pipeline().addLast(new ReadTimeoutHandler(5));
sc.pipeline().addLast(new ClientHandler());
}
});
} public void connect() {
try {
this.channelFuture = bootstrap.connect("127.0.0.1", 9999).sync();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } public ChannelFuture getChannelFuture() {
if (this.channelFuture == null) {
this.connect();
}
if (!this.channelFuture.channel().isActive()) {
this.connect();
}
return this.channelFuture;
} public static void main(String[] args) throws Exception { final Client client = getClientInstance();
client.connect();
ChannelFuture cf = client.getChannelFuture();
Data data = new Data();
data.setId(1);
data.setName("first");
cf.channel().writeAndFlush(data);
Thread.sleep(6000);
//因为设置的5秒超时 这里通过一个子线程 模拟再次连接
new Thread(new Runnable() {
public void run() {
System.out.println("进入子线程...");
ChannelFuture cf = client.getChannelFuture();
Data data = new Data();
data.setId(2);
data.setName("second");
cf.channel().writeAndFlush(data);
try {
cf.channel().closeFuture().sync();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("子线程结束!!");
}
}).start();
cf.channel().closeFuture().sync(); System.out.println("主线程结束!!");
}
}
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil; public class ClientHandler extends ChannelHandlerAdapter { /**
* 通道刚刚建立的时候 发送认证消息 (认证通过 建立连接 失败 关闭连接)
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
// ctx.channel().writeAndFlush("发送认证消息");
super.channelActive(ctx);
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
//do something msg
System.out.println("Client: " + (Data)msg);
} finally {
ReferenceCountUtil.release(msg);
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
一下是运行结果
服务器端
客户端
netty2 案例:数据通信的更多相关文章
- Netty 编解码技术 数据通信和心跳监控案例
Netty 编解码技术 数据通信和心跳监控案例 多台服务器之间在进行跨进程服务调用时,需要使用特定的编解码技术,对需要进行网络传输的对象做编码和解码操作,以便完成远程调用.Netty提供了完善,易扩展 ...
- 使用hessian+protocol buffer+easyUI综合案例--登陆
首先先简单介绍下hessian ,protocol buffer, easyUI框架 hessian: Hessian是一个轻量级的remoting on http工具,采用的是Binary RPC协 ...
- 第二篇:智能电网(Smart Grid)中的数据工程与大数据案例分析
前言 上篇文章中讲到,在智能电网的控制与管理侧中,数据的分析和挖掘.可视化等工作属于核心环节.除此之外,二次侧中需要对数据进行采集,数据共享平台的搭建显然也涉及到数据的管理.那么在智能电网领域中,数据 ...
- TCP/IP协议原理与应用笔记09:数据通信---封装
2016-08-091. 数据通信----封装: 2. 协议数据单元: PDU:对等层数据通信的单元. 比如Source端的应用层 和 Destination端的应用层是对等层(L7),这个时候L7 ...
- 《深入理解Java虚拟机》-----第5章 jvm调优案例分析与实战
案例分析 高性能硬件上的程序部署策略 例 如 ,一个15万PV/天左右的在线文档类型网站最近更换了硬件系统,新的硬件为4个CPU.16GB物理内存,操作系统为64位CentOS 5.4 , Resin ...
- 5、JVM--调优案例分析
5.1.案例分析 5.1.1.高性能硬件上的程序部署策略 假如一个15w/天左右的在线文档类型网站再准备更换硬件系统 新的硬件为4个CPU.16GB物理内存,操作系统为64为Cento是 Resin作 ...
- vue02—— 动画、组件、组件之间的数据通信
一.vue中使用动画 文档:https://cn.vuejs.org/v2/guide/transitions.html 1. Vue 中的过渡动画 <!DOCTYPE html> < ...
- Java之JVM调优案例分析与实战(2) - 集群间同步导致的内存溢出
环境:一个基于B/S的MIS系统,硬件为两台2个CPU.8GB内存的HP小型机,服务器是WebLogic 9.2,每台机器启动了3个WebLogic实例,构成一个6个节点的亲合式集群. 说明:由于是亲 ...
- KVM部署LVS集群故障案例一则
一.故障现象 KVM部署LVS(Linux Virtual Server)集群后,能够单独以HTTP方式访问RS(Real Server)的实际IP,但无法通过VIP(Virtual IP)访问. 二 ...
随机推荐
- 黄聪:用 CSS 实现元素垂直居中,有哪些好的方案?
1.不知道自己高度和父容器高度的情况下, 利用绝对定位只需要以下三行: parentElement{ position:relative; } childElement{ position: abso ...
- zabbix监控windows服务器
Zabbix agent 在windows上安装部署 1. 下载与解压 地址: http://www.zabbix.com/downloads/2.4.0/zabbix_agents_2.4.0.w ...
- Python中的正则表达式(re)
import re re.match #从开始位置开始匹配,如果开头没有则无 re.search #搜索整个字符串 re.findall #搜索整个字符串,返回一个list 举例: r(raw)用在p ...
- python学习笔记_week28
heap import heapq import random heap = [] data = list(range(10000)) random.shuffle(data) # for num i ...
- MySql:SELECT 语句(三) WHERE 指定查询条件
1.WHERE 子句条件操作符 包括:> .<.>=.<=.!= .=.BETWEEN ... AND ...(在指定的两个值之间) 示例: 1)select * from s ...
- jmeter 连接 MySql
1.连接 mysql 驱动包安装下载 1)首先需要安装 mysql 驱动包,下载地址:https://dev.mysql.com/downloads/connector/j/5.1.html 2)下载 ...
- 最适合入门的Laravel中级教程(一)
Laravel 是一个全栈框架: 我们使用 Laravel 开发业务常见有 3 个方向: 前端页面和后端逻辑混合的应用 主要是面向对 SEO 有需求的项目: 比如说新闻资讯博客文章等: 一般在控制器中 ...
- 项目(五)jumpserver企业开源跳板机搭建
跳板机是什么?跳板机是运维堡垒主机的另个称呼.作为技术或者运维人员应该不会陌生.企业为了服务器的安全,通常所有的ssh连接都是通过跳板机来完成,以便于对ssh连接进行验证和管理. 接下来,我来讲述一下 ...
- VueJs学习笔记
在cmd下,进入目录之后 cd 到项目目录下 1 安装node cnpm install 2 启动或者调试 cnpm start (或是npm run dev) 3 上线: npm run b ...
- Python开发【第五篇】:模块
递归的案例:阶乘 1*2*3*4*5*6*7- def func(num): if num == 1: return 1 return num * func(num - ...