netty初步
netty是java的高性能socket框架,linux下基epoll,这里不对他多牛逼作分析,网上资料很多,这里针对一般socket的业务作个例子
几个基本概念:
channel类似于socket句柄的抽象
pipeline是每个socket里面的eventHandler的处理响应链
每个socket(channel)绑定一个pipeline,,每个pipeline绑定若干个handler,netty里面的handler,专门用来处理和业务有关的东西,handler有upHandler和downHandler,down用来处理发包,up用来处理收包,大概的示例图看这里
注意上面的123的顺序,很重要,在netty里面,处理顺序如图,对于up类的收包处理,最靠近收包层的顺序越靠前;对于down类的包处理,最靠近收包层的顺序越靠后
还有一些encoder和decoder,encoder用来在发包之前进行加密,decoder在收包以后进行解码,然后业务数据跳到事件处理流程。
下面具体上代码,版本是netty3.6
MessageClientHandler.java
package com.netty.test.client; import java.util.logging.Level;
import java.util.logging.Logger; import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler; public class MessageClientHandler extends SimpleChannelUpstreamHandler { private static final Logger logger = Logger.getLogger(
MessageClientHandler.class.getName()); @Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) {
String message = "hello kafka0102";
e.getChannel().write(message);
} @Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
System.err.println("client messageReceived send message "+e.getMessage());
try {
Thread.sleep(1000*3);
} catch (Exception ex) {
ex.printStackTrace();
}
e.getChannel().write(e.getMessage());
} @Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
}
MessageDecoder.java
package com.netty.test.client;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder; public class MessageDecoder extends FrameDecoder { @Override
protected Object decode(
ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
if (buffer.readableBytes() < 4) {
return null;//(1)
}
int dataLength = buffer.getInt(buffer.readerIndex());
if (buffer.readableBytes() < dataLength + 4) {
return null;//(2)
} buffer.skipBytes(4);//(3)
byte[] decoded = new byte[dataLength];
buffer.readBytes(decoded);
String msg = new String(decoded);//(4)
return msg;
}
}
MessageEncoder.java
package com.netty.test.client;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; public class MessageEncoder extends OneToOneEncoder { @Override
protected Object encode(
ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
if (!(msg instanceof String)) {
return msg;//(1)
} String res = (String)msg;
byte[] data = res.getBytes();
int dataLength = data.length;
ChannelBuffer buf = ChannelBuffers.dynamicBuffer();//(2)
buf.writeInt(dataLength);
buf.writeBytes(data);
return buf;//(3)
}
}
用来测试的TestClientDownHandlerA.java
package com.netty.test.client; import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.SimpleChannelDownstreamHandler; public class TestClientDownHandlerA extends SimpleChannelDownstreamHandler { public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
System.err.println("test client Down handlerA "); super.handleDownstream(ctx, e);
}
}
用来测试的TestClientDownHandlerB.java
package com.netty.test.client; import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.SimpleChannelDownstreamHandler; public class TestClientDownHandlerB extends SimpleChannelDownstreamHandler { public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
System.err.println("test client Down handlerB "); super.handleDownstream(ctx, e);
}
}
MessageClientPipelineFactory.java
package com.netty.test.client; import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels; import com.netty.test.client.MessageDecoder;
import com.netty.test.client.MessageEncoder; public class MessageClientPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("decoder", new MessageDecoder());
pipeline.addLast("encoder", new MessageEncoder());
pipeline.addLast("handler", new MessageClientHandler()); pipeline.addFirst("testClientDownHandlerA", new TestClientDownHandlerA());
pipeline.addFirst("testClientDownHandlerB", new TestClientDownHandlerB()); return pipeline;
}
}
MessageClient.java
package com.netty.test.client; import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; public class MessageClient { public static void main(String[] args) throws Exception {
// Parse options.
String host = "127.0.0.1";
int port = 8888;
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new MessageClientPipelineFactory());
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection is closed or the connection attempt fails.
future.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
}
客户端代码完成
以下为服务端测试代码
MessageDecoder和Messagencoder照抄,这个都是一样的
MessageServerHandler.java
package com.netty.test.server;
import java.util.logging.Level;
import java.util.logging.Logger; import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler; public class MessageServerHandler extends SimpleChannelUpstreamHandler { private static final Logger logger = Logger.getLogger(
MessageServerHandler.class.getName()); @Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
if (!(e.getMessage() instanceof String)) {
return;//(1)
}
String msg = (String) e.getMessage();
System.err.println("got msg:"+msg);
e.getChannel().write(msg);//(2)
} @Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
}
TestServerUpHandlerA.java
package com.netty.test.server; import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler; public class TestServerUpHandlerA extends SimpleChannelUpstreamHandler { @Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
System.err.println("server test upHandlerA get message "+e.getMessage()); try {
super.messageReceived(ctx, e);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} @Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) { e.getChannel().close();
}
}
TestServerUpHandlerB.java
package com.netty.test.server; import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler; public class TestServerUpHandlerB extends SimpleChannelUpstreamHandler { @Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
System.err.println("server test upHandlerB get message "+e.getMessage()); try {
super.messageReceived(ctx, e);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} @Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) { e.getChannel().close();
}
}
MessageServerPipelineFactory.java
package com.netty.test.server; import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels; public class MessageServerPipelineFactory implements
ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("decoder", new MessageDecoder());
pipeline.addLast("encoder", new MessageEncoder());
pipeline.addLast("handler", new MessageServerHandler()); // pipeline.addFirst("testServerUpHandlerA", new TestServerUpHandlerA());
// pipeline.addFirst("testServerUpHandlerB", new TestServerUpHandlerB()); return pipeline;
}
}
MessageServer.java
package com.netty.test.server; import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; public class MessageServer { public static void main(String[] args) throws Exception {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool())); // Set up the default event pipeline.
bootstrap.setPipelineFactory(new MessageServerPipelineFactory()); // Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(8888));
}
}
通过测试,可以发现handler的处理顺序,和图上面的是一致的;还有可以参考下encoder和decoder的写法,改改,直接用于项目。
netty初步的更多相关文章
- NIO原理剖析与Netty初步----浅谈高性能服务器开发(一)
除特别注明外,本站所有文章均为原创,转载请注明地址 在博主不长的工作经历中,NIO用的并不多,由于使用原生的Java NIO编程的复杂性,大多数时候我们会选择Netty,mina等开源框架,但理解NI ...
- 架构师养成记--19.netty
一.Netty初步 为什么选择Netty? 和NIO比较,要实现一个通信要简单得很多,性能很好.分布式消息中间件.storm.Dubble都是使用Netty作为底层通信. Netty5.0要求jdk1 ...
- netty学习记录1
最近在学习netty,看的是<netty权威指南 第2版>. 然后看的同时也把书上面的代码一行行敲下来做练习,不过到第三章就出问题了. 按照书上讲的,sever/client端都需要继承C ...
- Socket网络通信编程(二)
1.Netty初步 2.HelloWorld 3.Netty核心技术之(TCP拆包和粘包问题) 4.Netty核心技术之(编解码技术) 5.Netty的UDP实现 6.Netty的WebSocket实 ...
- 初步了解 Netty
精通并发与 Netty (一)如何使用 精通并发与 Netty Netty 是一个异步的,事件驱动的网络通信框架,用于高性能的基于协议的客户端和服务端的开发. 异步指的是会立即返回,并不知道到底发送过 ...
- <Netty>(入门篇)TIP黏包/拆包问题原因及换行的初步解决之道
熟悉TCP编程的读者可能都知道,无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制.木章开始我们先简单介绍TCP粘包/拆包的基础知识,然后模拟一个没有考虑TCP ...
- java架构之路-(netty专题)初步认识BIO、NIO、AIO
本次我们主要来说一下我们的IO阻塞模型,只是不多,但是一定要理解,对于后面理解netty很重要的 IO模型精讲 IO模型就是说用什么样的通道进行数据的发送和接收,Java共支持3种网络编程IO模式: ...
- Netty学习摘记 —— 初步认识Netty核心组件
本文参考 我在博客内关于"Netty学习摘记"的系列文章主要是对<Netty in action>一书的学习摘记,文章中的代码也大多来自此书的github仓库,加上了一 ...
- Netty学习——Google Protobuf的初步了解
学习参考的官网: https://developers.google.com/protocol-buffers/docs/javatutorial 简单指南详解:这个文档写的简直是太详细了. 本篇从下 ...
随机推荐
- PatePoco中对sql参数化时Top参数化的问题
PatePoco中对sql参数化是直接用@+参数名来处理,但是想用如下语句时竟然报错了 SELECT TOP @num * FROM tableA 执行时抛出异常,根据错误提示搞了很久都没找到原因,最 ...
- Oracle 从共享池删除指定SQL的执行计划
ORACLE从共享池删除指定SQL的执行计划 2016-12-29 11:14 by 潇湘隐者, 2836 阅读, 0 评论, 收藏, 编辑 Oracle 11g在DBMS_SHARED_POOL包中 ...
- 20165210 Java第六周学习总结
20165210 Java第六周学习总结 教材学习内容 第八章学习总结 String类: 构造String对象: 1. 常量对象 2. String对象 3. 引用String常量 字符串的并置: S ...
- gulp 系统教程
移步: http://www.cnblogs.com/2050/p/4198792.html gulp外挂 加md5 版本号 自动合并图片并修改css的坐标 一个系统列子 gulp可以做哪些事情
- 结合P2P软件使用Ansible分发大文件
一 应用场景描述 现在我需要向50+数量的服务器分发Logstash新版本的rpm包,大概220MB左右,直接使用Ansible的copy命令进行传输,命令如下: 1 ansible all -m ...
- HDU 1590 Searching(求复数向量和的极限)
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...
- cocos2dx 3.1.1移植安卓apk (lua项目交叉编译 mac环境下)
cocos2dx 3.1.1 lua项目安卓交叉编译 mac环境下 本文基于ant,sdk,ndk,adt等软件和环境已经事前设置好 1\新建项目 在mac的终端下输入命令: cocos new te ...
- CentOS7安装OpenStack(Rocky版)-08.启动一个虚拟机实例
安装完openstack的必要组件keystone,nova,glance,neutron以后就可以使用openstack命令创建一台云虚拟机了 ------------------- 完美的分割线 ...
- C/C++ 字符串分割: strtok 与 strsep 函数说明
函数原型: char *strtok(char *s, const char *delim); char *strsep(char **s, const char *delim); 功能:strtok ...
- 一步步入门log4cpp
前言 项目实现过程中,需要检查.查找或者调试程序bug等,此时程序日志则较为清晰地展现代码的运行过程.目前接触到的方法有打印消息到控制台,将重要信息输出到某个文件比如txt文件,或者直接使用日志库. ...