自己基于netty封装的网络通信框架
作者:andyhc | 2012/6/5 12:17:54 | 阅读148次
最近在做一个项目,用到了远程调用方式,开始采用的是rmi,后来经过测试,rmi可能无法达到项目的一些性能上的要求,于是采用了基于tcp/udp的netty,但是直接用netty开发,有些麻烦了,我们想把服务抽取出来部署在远程服务器上,开发的兄弟们只是在自己的项目中负责调用一下,就跟rmi类似,非常方便。
但是又有一个问题,调用的兄弟需要在web中请求这种tcp服务,netty内部是异步处理机制,http是伪长连接,调用结束后,异步请求还没有返回,http连接就断开了,返回的是null。所以这个问题要解决一下。
下面说下封装的各个类的代码吧
首先当客户端对远程服务器发起tcp请求时,这时候请求一般会到达服务器端的handler里,我写的这个handler继承了netty的SimpleChannelUpstreamHandler,代码如下:
public abstract class ChannelServerHandler extends SimpleChannelUpstreamHandler {private final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelServerHandler.class);protected final Map<String, InvokeHandler> handlers = new HashMap<String, InvokeHandler>();protected final Map<String, Method> initMethods = new HashMap<String, Method>();public ChannelServerHandler() {WSCFInit.register(handlers, initMethods);}protected abstract void processor(Channel channel, Object message);@Overridepublic final void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {Transport t = (Transport) e.getMessage();String className = t.getClazz();String methodName = t.getMethod();logger.info("Invoke Handler:" + className + ", Invoke Method:" + methodName);processor(ctx.getChannel(), t);}
里面有几个变量需要解释一下,handlers是开发tcp服务端的handler存放的map,initMethods是里面需要调用的方法,通过WSCFInit类来进行初始化工作。
protected abstract void processor(Channel channel, Object message);这个方法具体的逻辑是由它的子类来处理的。
再看一下ServerHandler类里面processor的代码,这个类继承了ChannelServerHandler
@Overrideprotected void processor(Channel channel, Object message) {Transport transport = (Transport) message;InvokeHandler handler = handlers.get(transport.getClazz());Object[] params = (Object[]) transport.getMessage();Object ret = null;try {Method method = initMethods.get(transport.getClazz() + transport.getMethod());if (method == null) {} else {ret = method.invoke(handler, params);}ServerSender sender = new ServerSender(channel, transport);sender.send(ret);} catch (Exception e) {throw new IllegalAccessError(e.getMessage());}}
客户端向服务器端发起的请求真正处理的逻辑在这个方法里面,这个方法在处理完调用了相应的服务端handler进行响应后,会将需要返回给客户端的信息封装在transport这个对象然后传递出去,这个对象是封装服务器和客户端通信消息的。
那么Transport这个类定义了些什么内容呢
public final class Transport implements Serializable {private static final long serialVersionUID = 1675991188209117209L;private String clazz;private String method;private Object message;private String key;
clazz是要调用的handler的注解名,method是要调用的方法的注解名,message是封装通信消息的,key这个后面再说,是可以多次调用重复的url进行的唯一标识。
ok,处理服务端信息的handler看完了,我们再来看看客户端的
public abstract class ChannelClientHandler extends SimpleChannelUpstreamHandler {private final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelClientHandler.class);public final Map<String, ResultHandler> ret = new ConcurrentHashMap<String, ResultHandler>();protected abstract void processor(Channel channel, Object message);@Overridepublic void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {processor(ctx.getChannel(), e.getMessage());}}
ret是封装服务器端返回结果的,它的子类负责实现processor方法。
子类代码如下
@Overrideprotected void processor(Channel channel, Object message) {Transport t = (Transport) message;String key = t.getClazz() + t.getMethod() + t.getKey();ResultHandler r = ret.remove(key);r.processor(t.getMessage());}
ResultHandler这个是我定义的一个注解,专门处理异步返回的结果
上面说了如何处理netty内部的异步机制,让主线程能够等待异步返回的结果
处理代码如下
public Object get(String url, Object... params) {class Result {public Object o;}final Result ret = new Result();synchronized (ret) {try {invoke(url, params, new ResultHandler() {@Overridepublic void processor(Object message) {synchronized (ret) {ret.o = message;ret.notify();}}});ret.wait();} catch (InterruptedException e) {}return ret.o;}}
当客户端调用get方法时候,就可以得到服务器端异步返回的结果了。但是对客户端来说,他感觉到的是同步的调用。
最后我定义了一个InvokeHandler,当开发者开发服务端程序时候,需要实现这个接口,定义自己的handler
类似如下
@Handler(name="testhandler")public class Server1 implements InvokeHandler{@Remote(url="test2")public String say(String msg) {System.out.println(msg);return "hi";}@Remote(url= "test2")public String say2(Person p) {System.out.println(p.getId());return p.getName();}}
上面定义的这些注解,在WSCFInit初始化的时候会放到一个map里面,类似于spring的配置文件。
最后再说说客户端是怎么调用的,在连接好服务端ip和port后,通过如下调用方式就可以了
public class Client {private static ClientSender sender;public static void main(String[] args) {sender = ClientProxy.connect(ip, port);Object msg = sender.get("tcp://testhandler/test1", "hello");System.out.println(msg);Person p = new Person();p.setId(1);p.setName("zhangsan");Object o = sender.get("tcp://testhandler/test2", p);System.out.println(o);}}
这样就ok了,也可以自定义要传输的是对象还是xml还是json。同时可以方便的定义自己的解码器。完成自己的业务需求。
分享到:
相关推荐
【基于Netty封装的快速分布式任务开发框架】是一种高效、轻量级的解决方案,它将Netty的强大功能与分布式任务处理的灵活性相结合。Netty是一个高性能的异步事件驱动的网络应用程序框架,常用于构建高度可扩展的网络...
标题中的“基于Netty二次封装的Android链路通讯库,用以快速开发高性能”表明了这个项目是一个专为Android平台设计的通信库,它利用了Netty框架进行优化和封装,目的是为了简化开发者在构建高性能网络应用时的工作,...
在即时通信领域,Netty作为一个高性能、异步事件驱动的网络应用框架,广泛应用于各种复杂的通信系统。本项目“基于Netty的即时通信”旨在演示如何利用Netty构建一个简单的聊天应用,它包括服务端和客户端,实现了多...
Socket编程是网络通信的基础,而Netty则为构建基于Socket的服务端提供了强大的支持。 Netty的核心在于其使用了非阻塞I/O(Non-blocking I/O,也称为NIO)模型,这使得它在处理大量并发连接时表现出色。NIO是一种I/O...
- **异常处理**:确保有适当的错误处理机制,当业务逻辑或网络通信出错时,能提供友好的错误信息。 - **拦截器**:SpringMVC中的拦截器可以用来进行权限检查、日志记录等操作。在Netty中,可以实现类似的过滤器链。...
Netty 是一个高性能、...通过封装 HTTP、TCP 和 UDP,Netty 提供了一种统一的方式来处理多种网络通信方式,简化了网络编程的复杂性。学习并掌握 Netty,可以提升你在网络编程领域的专业技能,为你的职业生涯增添价值。
1. **Netty框架**:Netty的核心是它的NIO(非阻塞I/O)模型,它通过Selector和ChannelHandler实现了高效的网络通信。在WebSocket服务器端,Netty提供了WebSocketServerProtocolHandler来处理WebSocket握手和消息传输...
Netty框架是Java领域中广泛使用的高性能、异步事件驱动的...通过学习和实践这个"Netty框架各种通信C/S端"的资源,你可以深入理解Netty的工作原理,掌握高效网络编程技巧,为你的项目带来更稳定、高效的网络通信能力。
通过对这些组件的理解和实践,我们可以深入掌握Netty框架,实现高效的网络通信,包括文件上传、Socket通信以及UDP协议的运用。无论是在微服务、游戏服务器还是大数据传输等场景,Netty都能提供强大的性能和灵活性。...
在IT行业中,网络通信是至关重要的一个领域,TCP(传输控制协议)和UDP(用户数据报协议)作为两种主要的传输层协议,各有其特点和应用场景。本项目以"基于Netty实现的UDP通信"为主题,旨在通过源码和教程帮助开发者...
该入门示例程序是异步、基于事件驱动的网络通讯框架,对于java开发入门以及netty开发入门程序员有极大的学习效果和提升作用。异步:支持多个请求同时处理 响应通过回调函数处理 例如ajax 事件驱动 :比如客户端对...
金融交易系统往往有自己的通信协议,如TCP/IP之上封装的自定义协议。NETTY提供了强大的编码解码器机制,可以定制化处理这些协议。源码中的编解码器部分会实现对交易请求和响应的序列化和反序列化,确保数据在传输...
* Channel:Netty网络通信的主体,由它负责同对端进行网络通信、注册和数据操作等功能。 * Future:代表异步操作的结果。 * 事件和ChannelHandler:数据的读、写、状态的变换都可以称为事件;事件处理器是对事件的...
SOFA-BOLT是蚂蚁金融服务集团开发的一套基于Netty实现的网络通信框架,本质是一套Netty私有协议栈封装,目的是为了让开发者能将更多的精力放在基于网络通信的业务逻辑实现上,而不是过多的纠结于网络底层NIO的实现...
Netty是一个基于Java的高性能、高可靠性的网络应用程序框架,广泛用于实现各种网络协议,尤其是在需要处理大量并发连接的场景下。RPC(Remote Procedure Call)即远程过程调用,它是一种计算机通信协议。该协议允许...
Netty 在解决JDK自带的NIO API使用复杂性方面表现出色,提供了一套高度封装且功能丰富的API,使得开发者可以更加专注于业务逻辑的实现,而无需关心底层复杂的网络通信细节。 Netty 的核心组件包括: 1. **...
【标题】"基于Netty的GUI版聊天室"是一个实现多用户实时通信的项目,它利用了Netty框架和图形用户界面(GUI)技术。Netty是一个高性能、异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器和客户端...
ANetty是一个专为Android平台设计的网络通讯库,它是对著名的Java NIO框架Netty的一次深度封装,目的是为了简化Android开发者在网络编程上的工作。Netty本身是一个强大的、高效的网络应用框架,它提供了多种编解码器...
Netty底层基于Java NIO框架,但针对网络通信的复杂性和高并发场景进行了封装和优化,使得开发者能够更加专注于业务逻辑的实现。Netty的主要特点包括:高效的网络通信机制、灵活的线程模型、强大的协议支持、安全性...
此外,Netty的API设计易于理解和使用,使得开发者可以专注于业务逻辑,而无需过多关注底层网络通信的复杂性。 该压缩包中的"netty-4.1.16.Final"可能包含以下组件: 1. `netty-all`: 所有模块合并的jar包,便于一次...