Netty的简单Demo
这个demo是通过网上下载:
使用maven构建的:
项目结构:
pom.xml:
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.33.Final</version>
</dependency>
</dependencies>
客户端:
Client.java
package com.xys.client; import com.xys.common.CustomHeartbeatHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler; import java.util.Random;
import java.util.concurrent.TimeUnit; /**
* @author xiongyongshun
* @version 1.0
* @email yongshun1228@gmail.com
* @created 16/9/18 12:59
*/
public class Client {
private NioEventLoopGroup workGroup = new NioEventLoopGroup(4);
private Channel channel;
private Bootstrap bootstrap; public static void main(String[] args) throws Exception {
Client client = new Client();
client.start();
client.sendData();
} public void sendData() throws Exception {
Random random = new Random(System.currentTimeMillis());
for (int i = 0; i < 10000; i++) {
if (channel != null && channel.isActive()) {
String content = "client msg " + i;
ByteBuf buf = channel.alloc().buffer(5 + content.getBytes().length);
buf.writeInt(5 + content.getBytes().length);
buf.writeByte(CustomHeartbeatHandler.CUSTOM_MSG);
buf.writeBytes(content.getBytes());
channel.writeAndFlush(buf);
} Thread.sleep(random.nextInt(20000));
}
} public void start() {
try {
bootstrap = new Bootstrap();
bootstrap
.group(workGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline p = socketChannel.pipeline();
p.addLast(new IdleStateHandler(0, 0, 5));
p.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, -4, 0));
p.addLast(new ClientHandler(Client.this));
}
});
doConnect(); } catch (Exception e) {
throw new RuntimeException(e);
}
} protected void doConnect() {
if (channel != null && channel.isActive()) {
return;
} ChannelFuture future = bootstrap.connect("127.0.0.1", 12345); future.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture futureListener) throws Exception {
if (futureListener.isSuccess()) {
channel = futureListener.channel();
System.out.println("Connect to server successfully!");
} else {
System.out.println("Failed to connect to server, try connect after 10s"); futureListener.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
doConnect();
}
}, 10, TimeUnit.SECONDS);
}
}
});
} }
ClientHandler.java
package com.xys.client; import com.xys.common.CustomHeartbeatHandler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; /**
* @author xiongyongshun
* @version 1.0
* @email yongshun1228@gmail.com
* @created 16/9/18 13:08
*/
public class ClientHandler extends CustomHeartbeatHandler {
private Client client;
public ClientHandler(Client client) {
super("client");
this.client = client;
} @Override
protected void handleData(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) {
byte[] data = new byte[byteBuf.readableBytes() - 5];
byteBuf.skipBytes(5);
byteBuf.readBytes(data);
String content = new String(data);
System.out.println(name + " get content: " + content);
} @Override
protected void handleAllIdle(ChannelHandlerContext ctx) {
super.handleAllIdle(ctx);
sendPingMsg(ctx);
} @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
client.doConnect();
}
}
CustomHeartbeatHandler.java
package com.xys.common; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent; /**
* @author xiongyongshun
* @version 1.0
* @email yongshun1228@gmail.com
* @created 16/9/18 13:02
*/
public abstract class CustomHeartbeatHandler extends SimpleChannelInboundHandler<ByteBuf> {
public static final byte PING_MSG = 1;
public static final byte PONG_MSG = 2;
public static final byte CUSTOM_MSG = 3;
protected String name;
private int heartbeatCount = 0; public CustomHeartbeatHandler(String name) {
this.name = name;
} @Override
protected void channelRead0(ChannelHandlerContext context, ByteBuf byteBuf) throws Exception {
if (byteBuf.getByte(4) == PING_MSG) {
sendPongMsg(context);
} else if (byteBuf.getByte(4) == PONG_MSG){
System.out.println(name + " get pong msg from " + context.channel().remoteAddress());
} else {
handleData(context, byteBuf);
}
} protected void sendPingMsg(ChannelHandlerContext context) {
ByteBuf buf = context.alloc().buffer(5);
buf.writeInt(5);
buf.writeByte(PING_MSG);
buf.retain();
context.writeAndFlush(buf);
heartbeatCount++;
System.out.println(name + " sent ping msg to " + context.channel().remoteAddress() + ", count: " + heartbeatCount);
} private void sendPongMsg(ChannelHandlerContext context) {
ByteBuf buf = context.alloc().buffer(5);
buf.writeInt(5);
buf.writeByte(PONG_MSG);
context.channel().writeAndFlush(buf);
heartbeatCount++;
System.out.println(name + " sent pong msg to " + context.channel().remoteAddress() + ", count: " + heartbeatCount);
} protected abstract void handleData(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf); @Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
// IdleStateHandler 所产生的 IdleStateEvent 的处理逻辑.
if (evt instanceof IdleStateEvent) {
IdleStateEvent e = (IdleStateEvent) evt;
switch (e.state()) {
case READER_IDLE:
handleReaderIdle(ctx);
break;
case WRITER_IDLE:
handleWriterIdle(ctx);
break;
case ALL_IDLE:
handleAllIdle(ctx);
break;
default:
break;
}
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.err.println("88888888888");
} @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.err.println("---" + ctx.channel().remoteAddress() + " is active---");
} @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.err.println("---" + ctx.channel().remoteAddress() + " is inactive---");
} protected void handleReaderIdle(ChannelHandlerContext ctx) {
System.err.println("---READER_IDLE---");
} protected void handleWriterIdle(ChannelHandlerContext ctx) {
System.err.println("---WRITER_IDLE---");
} protected void handleAllIdle(ChannelHandlerContext ctx) {
System.err.println("---ALL_IDLE---");
}
}
服务端:
Server.java
package com.xys.server; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler; /**
* @author xiongyongshun
* @email yongshun1228@gmail.com
* @version 1.0
* @created 16/9/18 12:59
*/
public class Server {
public static void main(String[] args) {
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
NioEventLoopGroup workGroup = new NioEventLoopGroup(4);
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline p = socketChannel.pipeline();
p.addLast(new IdleStateHandler(10, 0, 0));
p.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, -4, 0));
p.addLast(new ServerHandler());
}
}); Channel ch = bootstrap.bind(12345).sync().channel();
ch.closeFuture().sync();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
ServerHandler.java
package com.xys.server; import com.xys.common.CustomHeartbeatHandler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext; /**
* @author xiongyongshun
* @version 1.0
* @email yongshun1228@gmail.com
* @created 16/9/18 13:08
*/
public class ServerHandler extends CustomHeartbeatHandler {
public ServerHandler() {
super("server");
} @Override
protected void handleData(ChannelHandlerContext channelHandlerContext, ByteBuf buf) {
byte[] data = new byte[buf.readableBytes() - 5];
ByteBuf responseBuf = Unpooled.copiedBuffer(buf);
buf.skipBytes(5);
buf.readBytes(data);
String content = new String(data);
System.out.println(name + " get content: " + content);
channelHandlerContext.write(responseBuf);
} @Override
protected void handleReaderIdle(ChannelHandlerContext ctx) {
super.handleReaderIdle(ctx);
System.err.println("---client " + ctx.channel().remoteAddress().toString() + " reader timeout, close it---");
ctx.close();
}
}
ChannelMap.java(保存xxx,以便服务端主动向客户端发送信息)
package com.xys.common;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext; import java.util.HashMap; public class ChannelMap {
public static int channelNum=0;
private static HashMap<String,ChannelHandlerContext> channelHashMap=null;//应改为concurrentHashmap以解决多线程冲突 private static HashMap<Integer,Integer> portMap = null; public static void addPort(Integer fidHashCode,Integer fid){
if(portMap==null){
portMap=new HashMap<>(100);
}
portMap.put(fidHashCode,fid);
} //map:通过value获取key(fid)
public static Integer getfidByCode(Integer fidHashCode){
if(portMap==null||portMap.isEmpty()){
return null;
}
return portMap.get(fidHashCode);
} public static HashMap<String, ChannelHandlerContext> getChannelHashMap() {
return channelHashMap;
} public static ChannelHandlerContext getChannelByName(String name){
if(channelHashMap==null||channelHashMap.isEmpty()){
return null;
}
return channelHashMap.get(name);
} public static void addChannel(String name,ChannelHandlerContext channel){
if(channelHashMap==null){
channelHashMap=new HashMap<>(100);
}
channelHashMap.put(name,channel);
channelNum++;
} public static int removeChannelByName(String name){
if(channelHashMap.containsKey(name)){
channelHashMap.remove(name);
return 0;
}else{
return 1;
}
} }
使用addChannel()方法将ChannelHandlerContext保存在Map中
服务端向客户端发送信息:
public boolean sendInfoToNettyClient(String fid,String info) {
ChannelFuture cf = null;
ChannelHandlerContext ctx = ChannelMap.getChannelByName(fid); if(ctx == null) {
log.debug("客户端没有被启动或出现异常!");
return false;
} ByteBuf responseBuf = Unpooled.directBuffer(16);
responseBuf.writeInt(5+info.getBytes().length);
responseBuf.writeByte(CustomHeartbeatHandler.CUSTOM_MSG);
responseBuf.writeBytes(info.getBytes());
cf = ctx.write(responseBuf); return cf != null?true:false;
}
Netty的简单Demo的更多相关文章
- Netty心跳简单Demo
前面简单地了解了一下IdleStateHandler,我们现在写一个简单的心跳demo: 1)服务器端每隔5秒检测服务器端的读超时,如果5秒没有接受到客户端的写请求,也就说服务器端5秒没有收到读事件, ...
- 设计模式之单例模式的简单demo
/* * 设计模式之单例模式的简单demo */ class Single { /* * 创建一个本类对象. * 和get/set方法思想一样,类不能直接调用对象 * 所以用private限制权限 * ...
- Spring的简单demo
---------------------------------------- 开发一个Spring的简单Demo,具体的步骤如下: 1.构造一个maven项目 2.在maven项目的pom.xml ...
- 使用Spring缓存的简单Demo
使用Spring缓存的简单Demo 1. 首先创建Maven工程,在Pom中配置 <dependency> <groupId>org.springframework</g ...
- Managed DirectX中的DirectShow应用(简单Demo及源码)
阅读目录 介绍 准备工作 环境搭建 简单Demo 显示效果 其他 Demo下载 介绍 DirectX是Microsoft开发的基于Windows平台的一组API,它是为高速的实时动画渲染.交互式音乐和 ...
- angular实现了一个简单demo,angular-weibo-favorites
前面必须说一段 帮客户做了一个过渡期的项目,唯一的要求就是速度,我只是会点儿基础的php,于是就用tp帮客户做了这个项目.最近和客户架构沟通,后期想把项目重新做一下,就用现在最流行的技术,暂时想的使用 ...
- Solr配置与简单Demo[转]
Solr配置与简单Demo 简介: solr是基于Lucene Java搜索库的企业级全文搜索引擎,目前是apache的一个项目.它的官方网址在http://lucene.apache.org/sol ...
- 二维码简单Demo
二维码简单Demo 一.视图 @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name=&qu ...
- android JNI 简单demo(2)它JNI demo 写
android JNI 简单demo(2)它JNI demo 写 一.搭建Cygwin 环境:http://blog.csdn.net/androidolblog/article/details/25 ...
随机推荐
- k8s之深入解剖Pod(一)
上文说了一下k8s的简单使用,接下来就让我们来具体深入了解一下Pod.为了避免篇幅太长,所以会分成几篇. 目录: Pod定义详解 静态Pod Pod容器共享Volume 一.Pod定义详解 先看一个简 ...
- 第四章 Sentinel--服务容错
我们接着承接上篇继续讲下去 : 第三章 Nacos Discovery–服务治理,开始第四篇的学习 第四章 Sentinel–服务容错 4.1 高并发带来的问题 在微服务架构中,我们将业务拆分成一个个 ...
- 太酷炫了!!我会Python 导包八种方法,你呢?
1. 直接 import 人尽皆知的方法,直接导入即可 >>> import os >>> os.getcwd() '/home/wangbm'复制代码 与此类似的 ...
- OSPF --- 不规则区域实验
OSPF不规则区域实验: 一.知识点整理: OSPF中路由器的角色(看图): 骨干路由器:路由器所有接口属于area 0 -->R3 非骨干路由器:路由器所有接口属于非area 0 --&g ...
- MySQL 5.6.38安装
#1.安装说明 本套安装方式适用于:CentOS6.X 或CentOS7.X系列的OS安装,此方法适用于MySQL5.6.xx版本的安装,如果是5.7版本的话不适合该配置. #2.准备安装环境 # N ...
- Spring源码深度解析之Spring MVC
Spring源码深度解析之Spring MVC Spring框架提供了构建Web应用程序的全功能MVC模块.通过策略接口,Spring框架是高度可配置的,而且支持多种视图技术,例如JavaServer ...
- [LeetCode]547. Friend Circles朋友圈数量--不相邻子图问题
/* 思路就是遍历所有人,对于每一个人,寻找他的好友,找到好友后再找这个好友的好友 ,这样深度优先遍历下去,设置一个flag记录是否已经遍历了这个人. 其实dfs真正有用的是flag这个变量,因为如果 ...
- mysql explain参数详解
主要对几个参数做一些记录 type:显示的是访问类型 从最好到最差的连接类型为:const.eq_reg.ref.range.index和ALL 至少要达到range,基本是ref 最好是const ...
- 自动化运维工具-Ansible之5-流程控制
自动化运维工具-Ansible之5-流程控制 目录 自动化运维工具-Ansible之5-流程控制 playbook条件语句 单条件 多条件 多条件运算 示例 playbook循环语句 with_ite ...
- eclipse开启的时候adb.exe会自动开启么 怎么让它跟着eclipse自动开启
会的,Eclipse 参数页中的 General > Startup and Shutdown 中默认 Android Development Tools 是自动激活的,它会启动 adb.exe ...