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)访问. 二 ...
随机推荐
- 彻底删除msde2008(请先在控制面板中卸载).bat
彻底删除msde2008(请先在控制面板中卸载).bat @echo offset /P dv=请确认强制删除MSDE2008(请先在控制面板中卸载),Y=删除,N=退出:if not defined ...
- 2018-2019-2 20175227张雪莹 《Java程序设计》 实验一 Java开发环境的熟悉
2018-2019-2 20175227张雪莹<Java程序设计> 实验一 Java开发环境的熟悉 一.实验报告封面 课程:Java程序设计 班级:1752班 姓名:张雪莹 学号:2017 ...
- C++Primer第五版——习题答案详解(六)
习题答案目录:https://www.cnblogs.com/Mered1th/p/10485695.html 第7章 类 练习7.1 class Sales_data { public: std:: ...
- BottomNavigationView 使用
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.Cons ...
- sync;sync;sync;reboot
Sync命令 在用reboot命令启动unix系统后,系统提示出错信息,部分应用程序不能正常工作.经仔细检查系统文件,并和初始的正确备份进行比较,发现某些文件确实被破坏了,翻来覆去找不到文件遭破坏的原 ...
- Vue 路由及路由默认跳转
路由就是让根组件动态得去挂载其他组件: 步骤: //路由配置: //.安装 npm install vue-router --save / cnpm install vue-router --save ...
- OpenStack Trove组件WSGI和RPC调用流程(参考调用的整个过程)
参考博文:https://blog.csdn.net/bill_xiang_/article/details/72909927
- 非常优秀的swiper插件————幻灯片播放、图片轮播
http://www.idangero.us/ http://www.swiper.com.cn/ Swiper中文网 2015-10-15 SuperSlide2: (这是个PC用的滚屏插件,看着不 ...
- TCARS: Time- and Community-Aware Recommendation System(时间感知和社区感知推荐系统)
随着用户在物品上产生了大量行为,推荐系统成为了线上系统的重要组成部分.推荐系统算法使用用户对物品的行为信息以及上下文数据为每个用户推荐一组物品.算法根据用户之间及物品之间的相似度建立.本文介绍了一个基 ...
- IDLE的GUI交互模式下完美清屏
IDLE的GUI交互模式下完美清屏==============================================================================1.首先把 ...