在实际的项目中应该如何使用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 案例:数据通信的更多相关文章

  1. Netty 编解码技术 数据通信和心跳监控案例

    Netty 编解码技术 数据通信和心跳监控案例 多台服务器之间在进行跨进程服务调用时,需要使用特定的编解码技术,对需要进行网络传输的对象做编码和解码操作,以便完成远程调用.Netty提供了完善,易扩展 ...

  2. 使用hessian+protocol buffer+easyUI综合案例--登陆

    首先先简单介绍下hessian ,protocol buffer, easyUI框架 hessian: Hessian是一个轻量级的remoting on http工具,采用的是Binary RPC协 ...

  3. 第二篇:智能电网(Smart Grid)中的数据工程与大数据案例分析

    前言 上篇文章中讲到,在智能电网的控制与管理侧中,数据的分析和挖掘.可视化等工作属于核心环节.除此之外,二次侧中需要对数据进行采集,数据共享平台的搭建显然也涉及到数据的管理.那么在智能电网领域中,数据 ...

  4. TCP/IP协议原理与应用笔记09:数据通信---封装

    2016-08-091. 数据通信----封装: 2. 协议数据单元: PDU:对等层数据通信的单元. 比如Source端的应用层 和 Destination端的应用层是对等层(L7),这个时候L7 ...

  5. 《深入理解Java虚拟机》-----第5章 jvm调优案例分析与实战

    案例分析 高性能硬件上的程序部署策略 例 如 ,一个15万PV/天左右的在线文档类型网站最近更换了硬件系统,新的硬件为4个CPU.16GB物理内存,操作系统为64位CentOS 5.4 , Resin ...

  6. 5、JVM--调优案例分析

    5.1.案例分析 5.1.1.高性能硬件上的程序部署策略 假如一个15w/天左右的在线文档类型网站再准备更换硬件系统 新的硬件为4个CPU.16GB物理内存,操作系统为64为Cento是 Resin作 ...

  7. vue02—— 动画、组件、组件之间的数据通信

    一.vue中使用动画 文档:https://cn.vuejs.org/v2/guide/transitions.html 1. Vue 中的过渡动画 <!DOCTYPE html> < ...

  8. Java之JVM调优案例分析与实战(2) - 集群间同步导致的内存溢出

    环境:一个基于B/S的MIS系统,硬件为两台2个CPU.8GB内存的HP小型机,服务器是WebLogic 9.2,每台机器启动了3个WebLogic实例,构成一个6个节点的亲合式集群. 说明:由于是亲 ...

  9. KVM部署LVS集群故障案例一则

    一.故障现象 KVM部署LVS(Linux Virtual Server)集群后,能够单独以HTTP方式访问RS(Real Server)的实际IP,但无法通过VIP(Virtual IP)访问. 二 ...

随机推荐

  1. SQL 语句 explain 分析

      分析索引的效率: > EXPLAIN sql; EXPLAIN 分析的结果的表头如下: id | select_type | table | partitions | type | poss ...

  2. <Vector Calculus>(by Paul C, Matthews) Notes

    现在流行用Exterior Caculus, 所以个人觉得Matthews这本书有点过时了. 想学Vector Calculus的话,推荐<Vector Calculus, Linear Alg ...

  3. 算法实践--最长递增子序列(Longest Increasing Subsquence)

    什么是最长递增子序列(Longest Increasing Subsquence) 对于一个序列{3, 2, 6, 4, 5, 1},它包含很多递增子序列{3, 6}, {2,6}, {2, 4, 5 ...

  4. 基础 - 字符读取函数scanf、getchar、gets、cin(清空缓存区解决单字符回车问题)

    0x01 scanf.getchar.cin读取单字符: 如下: //scanf读取字符 回车问题 void Sub_1_1() { char v1,v2; scanf("%c", ...

  5. 受限玻尔兹曼机(Restricted Boltzmann Machine, RBM) 简介

    受限玻尔兹曼机(Restricted Boltzmann Machine,简称RBM)是由Hinton和Sejnowski于1986年提出的一种生成式随机神经网络(generative stochas ...

  6. 学习 MeteoInfo二次开发教程(三)

    1.breakList的问题 ((PolygonBreak) aLS.breakList[0]).DrawFill=false; 新的类库将LegendScheme的breakList属性改为了Leg ...

  7. Android 开发 VectorDrawable 矢量图 (三)矢量图动画

    VectorDrawable 矢量图 三部曲: Android 开发 VectorDrawable 矢量图 (一)了解Android矢量图与获取矢量图 Android 开发 VectorDrawabl ...

  8. python3 列表去除重复项保留原序

    l1 = ['a',1,'c','b',2,'b','c','d','a'] l2= sorted(set(l1),key=l1.index) print('l2:',l2) print('l1:', ...

  9. indexOf() 如何判断一个元素在指定数组中是否存在? 找出指定元素出现的所有位置? indexOf()方法 是正序查找,lastIndexOf()是倒叙查找

    indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1. let a = [2, 9, 7, 8, 9]; a.indexOf(2); // 0 a.indexOf ...

  10. chrome.debugger

    官网: https://chromedevtools.github.io/devtools-protocol/ https://developer.chrome.com/extensions/debu ...