在实际的项目中应该如何使用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. C#编程经验-选择结构和循环结构

    选择结构:if elseif else ifswitch 循环结构:whiledo whilefor()foreach() 种类太多,不便记忆,人脑要记多种结构,要用的时候一种也把握不住所以,为方便记 ...

  2. sqlserver 带输出参数的存储过程的创建与执行

    创建 use StudentManager go if exists(select * from sysobjects where name='usp_ScoreQuery4') drop proce ...

  3. aspose.cells 插入图片

    ,,"d:\\1.jpg"); Aspose.Cells.Drawing.Picture pic = worksheet.Pictures[iIndex]; pic.Placeme ...

  4. Nginx、HAProxy、LVS三者的优缺点

    一.Nginx优点: 1.工作在网络7层之上,可针对http应用做一些分流的策略,如针对域名.目录结构,它的正规规则比HAProxy更为强大和灵活,所以,目前为止广泛流行. 2.Nginx对网络稳定性 ...

  5. 团队第三次 # scrum meeting

    github 本此会议项目由PM召开,召开时间为4-7日晚上9点 召开时长15分钟 任务表格 袁勤 继续学习SpringBoot https://github.com/buaa-2016/phyweb ...

  6. 系统变量之System.getenv()和System.getProperty()

    Java提供了System类的静态方法getenv()和getProperty()用于返回系统相关的变量与属性,getenv方法返回的变量大多于系统相关,getProperty方法返回的变量大多与ja ...

  7. 浅谈Cookie与Session技术

      一.什么是状态管理 将客户端与服务器之间多次交互当做一个整体来看,并且将多次交互所涉及的数据(状态)保存下来. 会话:当用户打开浏览器,访问多个WEB资源,然后关闭浏览器的过程,称之为一个会话,选 ...

  8. java细节知识

    代码优化细节 (1)尽量指定类.方法的final修饰符 带有final修饰符的类是不可派生的.在Java核心API中,有许多应用final的例子,例如java.lang.String,整个类都是fin ...

  9. 解决PHP使用POST提交数据不完整,数据不全的问题

    在后台form中,通过ajax请求返回了一个有很多input的form表单,提交数据后,要格式化数组时发现提交过来的数据不完整. PHP从5.3.9开始 php.ini 增加一个变量 max_inpu ...

  10. Android应用开发中,第三方集成新浪微博(sinaWeiboSDK)的过程记录

    作为一个android开发人员,不可避免的要学会使用和集成第三方API的能力 而新浪微博作为现在最主要的新闻速递媒体,使用十分普遍,并且提供了较为详细的API接入方法,故此选择集成sinaWeibiS ...