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 ...
随机推荐
- CentOS6下的ElasticSearch运行步骤
如何运行ElasticSearch: 1.首先安装jdk1.8版本或以上. 2.下载elasticsearch的压缩包.(我下载的是elasticsearch-6.3.2.tar.gz) 3.使用命令 ...
- Shiro实现Basic认证
前言 今天跟小伙伴们分享一个实战内容,使用Spring Boot+Shiro实现一个简单的Http认证. 场景是这样的,我们平时的工作中可能会对外提供一些接口,如果这些接口不做一些安全认证,什么人都可 ...
- Eureka 集群Demo
由于自己遇到了一些eureka集群疑问,就自己搭了一个集群demo进行测试.测试中通过两个eureka相互注册形成集群,两个服务提供者向eureka中注册服务,两个服务消费者通过feign进行服务调用 ...
- 第六章 Sleuth--链路追踪
修整了2天,我们继续接着上篇 第五章 Gateway–服务网关 继续来讲SpringCloud Alibaba全家桶中的 Sleuth 链路追踪 组件 喜欢记得点关注哦 6.1 链路追踪介绍 在大型系 ...
- 面试级解析HashMap
------------恢复内容开始------------ 在介绍HashMap之前,有必要先给大家介绍一些参数的概念 HashMap的最大容量,capacity译为容量,capacity就是指Ha ...
- 学习tomcat-如何建立连接,处理请求
tomcat如何建立连接,处理请求 学习探讨tomcat如何建立网络连接协议,并处理客户端过来的请求 建立http网络连接,指定通信协议 tomcat在创建时,会创建连接对象,负责处理客户端的请求,基 ...
- robotframework脚本中的文档注释
生成文档命令 python -m robot.libdoc xxx.robot xxx.html 语法说明 = 说明 = h2标题,注意第一个等号前有四个空格,==中间文字两边各有一个空格 == ...
- matlab双坐标轴设定
clc; clear all; close all; x1 = 0:.1:40; y1 = 4 * cos(x1)./(x1 + 2); x2 = 1:.2:20; y2 = x2.^2 ./ x2. ...
- element-ui 表单 v-if 不能验证问题
element-ui 表单v-if 很多人会遇到无法验证的问题,网上很多是在el-form-item标签前加一个div然后把v-if拿到div上去像这样 <div v-if="addc ...
- Mac如何下载软件
1.App Store 2.软件官网 3.Mac软件网站 4.搜狗微信 个人首选App Store,里面的软件安全可靠,其次就是官网,必不得已才去其他网站下载,毕竟不是App Store或官网 ...