一、 java NIO简介
nio是java New IO的简称,在jdk1.4里提供的新api。Sun官方标榜的特性如下:
为所有的原始类型提供(Buffer)缓存支持。
字符集编码解码解决方案。
Channel:一个新的原始I/O抽象。
支持锁和内存映射文件的文件访问接口。
提供多路(non-bloking)非阻塞式的高伸缩性网络I/O。
关于java NIO的实现部分不是本文讨论的重点,有兴趣的朋友可以访问JAVA夜无眠的博客JAVA NIO 实例。
二、 NIO框架简介
在Java社区,最知名的开源Java NIO框架要属Mina和Netty。实际上,Netty的作者原来就是Mina作者之一,所以可以想到,Netty和Mina在设计理念上会有很多共同点。而本文主要介绍的是使用netty搭建简单的游戏服务器,对于netty与mina的比较以及简单netty应用教程,将在其他文章中有所提及,敬请关注!
三、 netty游戏框架搭建
a) ServerBootstrap——netty框架的总入口
b) ChannelPipeline
channelPipeline是一系列channelHandler的集合,他参照J2ee中的Intercepting Filter模式来实现的,让用户完全掌握如果在一个handler中处理事件,同时让pipeline里面的多个handler可以相互交互。
c) Decoder——消息解码器
Decoder解码器继承于FrameDecoder,FrameDecoder是Netty codec包中的辅助类,它是个ChannelUpstreamHandler,decode方法是FrameDecoder子类需要实现的。在本程序采用的是LengthFieldBasedFrameDecoder。LengthFieldBasedFrameDecoder是基于长度字段的解码器。如果协议格式类似“内容长度”+内容、“固定头”+“内容长度”+动态内容这样的格式,就可以使用该解码器 。至于其他类型的解码器,这里不再一一介绍。
d) ServerHandler——消息分发器
在介绍这个类之前,先对几个概念进行简要说明:
1. Channel:channel 是负责数据读、写的对象。channel是双向的,既可以write 也可以read。而且在NIO中用户不应该直接从channel中读写数据,而是应该通过buffer,通过buffer再将数据读写到channel中。
一个channel 可以提供给用户下面几个信息
(1)channel的当前状态,比如open 还是closed
(2)ChannelConfig对象,表示channel的一些参数,比如bufferSize
(3)channel支持的所有i/o操作(比如read,write,connect.bind)
2. channelEvent:ChannelEvent广义的认为Channel相关的事件处理。他分为Upstream events和downstream events两大块。如果以服务器端为主体,那么client到server的数据传输过程是Upstream,而server到client的数据传输过程则是downstream;以客户端为主体的过程正好相反。一下主要介绍以服务器端为主体的开发。
3. 常用的Upstream events包括
a) messageReceived:信息被接受时 ---MessageEvent
b) exceptionCaught:产生异常时 ---ExceptionEvent
c) channelOpen:channel被开启时 ---ChannelStateEvent
d) channelClosed:channel被关闭时 ---ChannelStateEvent
e) channelBound:channel被开启并准备去连接但还未连接上的时候 ---ChannelStateEvent
f) channelUnbound:channel被开启不准备去连接时候 ---ChannelStateEvent
g) channelConnected:channel被连接上的时候 ---ChannelStateEvent
h) channelDisconnected:channel连接断开的时候 ---ChannelStateEvent
在本游戏架构里,ServerHandler扮演着创建线程、验证消息、分发消息的重要角色,程序如下:
需要注意的是:HandlerDispatcher是一个多线程处理器,用于处理游戏逻辑请求。这部分功能可根据用户的不同需求进行定制。
e) Encoder——消息编码器
消息编码器主要完成的是对游戏逻辑处理器返回的数据进行编码,组合成符合客户端规范的消息格式并发送。
nio是java New IO的简称,在jdk1.4里提供的新api。Sun官方标榜的特性如下:
为所有的原始类型提供(Buffer)缓存支持。
字符集编码解码解决方案。
Channel:一个新的原始I/O抽象。
支持锁和内存映射文件的文件访问接口。
提供多路(non-bloking)非阻塞式的高伸缩性网络I/O。
关于java NIO的实现部分不是本文讨论的重点,有兴趣的朋友可以访问JAVA夜无眠的博客JAVA NIO 实例。
二、 NIO框架简介
在Java社区,最知名的开源Java NIO框架要属Mina和Netty。实际上,Netty的作者原来就是Mina作者之一,所以可以想到,Netty和Mina在设计理念上会有很多共同点。而本文主要介绍的是使用netty搭建简单的游戏服务器,对于netty与mina的比较以及简单netty应用教程,将在其他文章中有所提及,敬请关注!
三、 netty游戏框架搭建
a) ServerBootstrap——netty框架的总入口
- /**
- * 作者:chenpeng
- * E-mail:46731706@qq.com
- * 创建时间:2012-7-12 下午12:22:53
- * 类说明 netty game
- */
- public class ServerTest {
- public static void main(String[] args) {
- DOMConfigurator.configureAndWatch("config/log4j.xml");
- ApplicationContext factory = new FileSystemXmlApplicationContext(
- new String[] { "config/propholder.xml" });
- ServerBootstrap bootstrap = new ServerBootstrap(
- new NioServerSocketChannelFactory(
- Executors.newCachedThreadPool(),
- Executors.newCachedThreadPool()));
- ServerPipelineFactory httpServerPipelineFactory=(ServerPipelineFactory)factory.getBean("serverPipelineFactory");
- bootstrap.setPipelineFactory(httpServerPipelineFactory);
- //启动端口 8888
- bootstrap.bind(new InetSocketAddress(8888));
- System.out.print("8888 server is starting……");
- }
- }
/** * 作者:chenpeng * E-mail:46731706@qq.com * 创建时间:2012-7-12 下午12:22:53 * 类说明 netty game */ public class ServerTest { public static void main(String[] args) { DOMConfigurator.configureAndWatch("config/log4j.xml"); ApplicationContext factory = new FileSystemXmlApplicationContext( new String[] { "config/propholder.xml" }); ServerBootstrap bootstrap = new ServerBootstrap( new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); ServerPipelineFactory httpServerPipelineFactory=(ServerPipelineFactory)factory.getBean("serverPipelineFactory"); bootstrap.setPipelineFactory(httpServerPipelineFactory); //启动端口 8888 bootstrap.bind(new InetSocketAddress(8888)); System.out.print("8888 server is starting……"); } }
b) ChannelPipeline
channelPipeline是一系列channelHandler的集合,他参照J2ee中的Intercepting Filter模式来实现的,让用户完全掌握如果在一个handler中处理事件,同时让pipeline里面的多个handler可以相互交互。
- import org.jboss.netty.channel.ChannelPipeline;
- import org.jboss.netty.channel.ChannelPipelineFactory;
- import org.jboss.netty.channel.Channels;
- import com.cp.netty.coder.Decoder;
- import com.cp.netty.coder.Encoder;
- /**
- * 作者:chenpeng
- * E-mail:46731706@qq.com
- * 创建时间:2012-7-12 上午11:28:56
- * channelPipeline是一系列channelHandler的集合,他参照J2ee中的Intercepting Filter模式来实现的,
- * 让用户完全掌握如果在一个handler中处理事件,同时让pipeline里面的多个handler可以相互交互
- */
- public class ServerPipelineFactory implements ChannelPipelineFactory {
- public ServerHandler serverHandler;
- public ChannelPipeline getPipeline() throws Exception {
- ChannelPipeline pipeLine = Channels.pipeline();
- pipeLine.addLast("decoder", new Decoder(Integer.MAX_VALUE, 0, 4));
- pipeLine.addLast("encoder", new Encoder(4));
- pipeLine.addLast("handler", serverHandler);
- return pipeLine;
- }
- public ServerHandler getServerHandler() {
- return serverHandler;
- }
- public void setServerHandler(ServerHandler serverHandler) {
- this.serverHandler = serverHandler;
- }
- }
import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.Channels; import com.cp.netty.coder.Decoder; import com.cp.netty.coder.Encoder; /** * 作者:chenpeng * E-mail:46731706@qq.com * 创建时间:2012-7-12 上午11:28:56 * channelPipeline是一系列channelHandler的集合,他参照J2ee中的Intercepting Filter模式来实现的, * 让用户完全掌握如果在一个handler中处理事件,同时让pipeline里面的多个handler可以相互交互 */ public class ServerPipelineFactory implements ChannelPipelineFactory { public ServerHandler serverHandler; public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeLine = Channels.pipeline(); pipeLine.addLast("decoder", new Decoder(Integer.MAX_VALUE, 0, 4)); pipeLine.addLast("encoder", new Encoder(4)); pipeLine.addLast("handler", serverHandler); return pipeLine; } public ServerHandler getServerHandler() { return serverHandler; } public void setServerHandler(ServerHandler serverHandler) { this.serverHandler = serverHandler; } }
c) Decoder——消息解码器
Decoder解码器继承于FrameDecoder,FrameDecoder是Netty codec包中的辅助类,它是个ChannelUpstreamHandler,decode方法是FrameDecoder子类需要实现的。在本程序采用的是LengthFieldBasedFrameDecoder。LengthFieldBasedFrameDecoder是基于长度字段的解码器。如果协议格式类似“内容长度”+内容、“固定头”+“内容长度”+动态内容这样的格式,就可以使用该解码器 。至于其他类型的解码器,这里不再一一介绍。
- 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.LengthFieldBasedFrameDecoder;
- /**
- * 作者:chenpeng
- * E-mail:46731706@qq.com
- * 创建时间:2012-7-12 上午11:22:14
- * 协议解码器
- */
- public class Decoder extends LengthFieldBasedFrameDecoder {
- // 第一个参数为信息最大长度,超过这个长度回报异常,
- // 第二参数为长度属性的起始(偏移)位,我们的协议中长度是0到第3个字节,所以这里写0,
- // 第三个参数为“长度属性”的长度,我们是4个字节,所以写4,
- // 第四个参数为长度调节值,在总长被定义为包含包头长度时,修正信息长度,
- // 第五个参数为跳过的字节数,根据需要我们跳过前4个字节,以便接收端直接接受到不含“长度属性”的内容。
- public Decoder(int maxFrameLength, int lengthFieldOffset,
- int lengthFieldLength) {
- super(maxFrameLength, lengthFieldOffset, lengthFieldLength);
- }
- @Override
- protected Object decode(ChannelHandlerContext ctx, Channel channel,
- ChannelBuffer buffer) throws Exception {
- ChannelBuffer buffs = (ChannelBuffer)super.decode(ctx, channel, buffer);
- return buffs;
- }
- }
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.LengthFieldBasedFrameDecoder; /** * 作者:chenpeng * E-mail:46731706@qq.com * 创建时间:2012-7-12 上午11:22:14 * 协议解码器 */ public class Decoder extends LengthFieldBasedFrameDecoder { // 第一个参数为信息最大长度,超过这个长度回报异常, // 第二参数为长度属性的起始(偏移)位,我们的协议中长度是0到第3个字节,所以这里写0, // 第三个参数为“长度属性”的长度,我们是4个字节,所以写4, // 第四个参数为长度调节值,在总长被定义为包含包头长度时,修正信息长度, // 第五个参数为跳过的字节数,根据需要我们跳过前4个字节,以便接收端直接接受到不含“长度属性”的内容。 public Decoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) { super(maxFrameLength, lengthFieldOffset, lengthFieldLength); } @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { ChannelBuffer buffs = (ChannelBuffer)super.decode(ctx, channel, buffer); return buffs; } }
d) ServerHandler——消息分发器
在介绍这个类之前,先对几个概念进行简要说明:
1. Channel:channel 是负责数据读、写的对象。channel是双向的,既可以write 也可以read。而且在NIO中用户不应该直接从channel中读写数据,而是应该通过buffer,通过buffer再将数据读写到channel中。
一个channel 可以提供给用户下面几个信息
(1)channel的当前状态,比如open 还是closed
(2)ChannelConfig对象,表示channel的一些参数,比如bufferSize
(3)channel支持的所有i/o操作(比如read,write,connect.bind)
2. channelEvent:ChannelEvent广义的认为Channel相关的事件处理。他分为Upstream events和downstream events两大块。如果以服务器端为主体,那么client到server的数据传输过程是Upstream,而server到client的数据传输过程则是downstream;以客户端为主体的过程正好相反。一下主要介绍以服务器端为主体的开发。
3. 常用的Upstream events包括
a) messageReceived:信息被接受时 ---MessageEvent
b) exceptionCaught:产生异常时 ---ExceptionEvent
c) channelOpen:channel被开启时 ---ChannelStateEvent
d) channelClosed:channel被关闭时 ---ChannelStateEvent
e) channelBound:channel被开启并准备去连接但还未连接上的时候 ---ChannelStateEvent
f) channelUnbound:channel被开启不准备去连接时候 ---ChannelStateEvent
g) channelConnected:channel被连接上的时候 ---ChannelStateEvent
h) channelDisconnected:channel连接断开的时候 ---ChannelStateEvent
在本游戏架构里,ServerHandler扮演着创建线程、验证消息、分发消息的重要角色,程序如下:
- import java.util.concurrent.ConcurrentLinkedQueue;
- import org.apache.log4j.Logger;
- import org.jboss.netty.buffer.ChannelBuffer;
- 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;
- import com.cp.game.HandlerDispatcher;
- import com.cp.game.domain.MessageQueue;
- import com.cp.netty.domain.GameRequest;
- /**
- * 作者:chenpeng
- * E-mail:46731706@qq.com
- * 创建时间:2012-7-12 下午12:02:52
- * 游戏协议接收分发器
- */
- public class ServerHandler extends SimpleChannelUpstreamHandler {
- public Logger log = Logger.getLogger(this.getClass());
- public static HandlerDispatcher handlerDispatcher;
- public void init() {
- new Thread(handlerDispatcher).start();
- }
- /* (non-Javadoc)
- * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#channelConnected(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.ChannelStateEvent)
- * 建立一个新channel
- */
- @Override
- public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
- throws Exception {
- log.debug("进来一个channel:" + ctx.getChannel().getId());
- MessageQueue messageQueue = new MessageQueue(
- new ConcurrentLinkedQueue<GameRequest>());
- handlerDispatcher.addMessageQueue(ctx.getChannel().getId(), messageQueue);
- }
- /* (non-Javadoc)
- * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#channelDisconnected(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.ChannelStateEvent)
- * 玩家主动关闭channel
- */
- @Override
- public void channelDisconnected(ChannelHandlerContext ctx,
- ChannelStateEvent e) throws Exception {
- log.error("关掉一个channel:" + ctx.getChannel().getId());
- handlerDispatcher.removeMessageQueue(e.getChannel().getId().toString());
- e.getChannel().close();
- }
- /* (non-Javadoc)
- * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#exceptionCaught(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.ExceptionEvent)
- * 玩家被动关闭channel
- */
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
- throws Exception {
- log.error("出异常啦……" + ctx.getChannel().getId());
- e.getCause().printStackTrace();
- handlerDispatcher.removeMessageQueue(e.getChannel().getId().toString());
- e.getChannel().close();
- }
- /* (non-Javadoc)
- * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#messageReceived(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.MessageEvent)
- * 消息接收处理器
- */
- @Override
- public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
- throws Exception {
- ChannelBuffer buffs = (ChannelBuffer) e.getMessage();
- buffs.skipBytes(4);// 越过dataLength的字节
- byte[] decoded = new byte[buffs.readableBytes()];
- buffs.readBytes(decoded);
- GameRequest gameRequest = new GameRequest(e.getChannel(), decoded);
- // 通知回调协议
- handlerDispatcher.addMessage(gameRequest);
- }
- public HandlerDispatcher getHandlerDispatcher() {
- return handlerDispatcher;
- }
- public void setHandlerDispatcher(HandlerDispatcher handlerDispatcher) {
- ServerHandler.handlerDispatcher = handlerDispatcher;
- }
- }
import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.log4j.Logger; import org.jboss.netty.buffer.ChannelBuffer; 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; import com.cp.game.HandlerDispatcher; import com.cp.game.domain.MessageQueue; import com.cp.netty.domain.GameRequest; /** * 作者:chenpeng * E-mail:46731706@qq.com * 创建时间:2012-7-12 下午12:02:52 * 游戏协议接收分发器 */ public class ServerHandler extends SimpleChannelUpstreamHandler { public Logger log = Logger.getLogger(this.getClass()); public static HandlerDispatcher handlerDispatcher; public void init() { new Thread(handlerDispatcher).start(); } /* (non-Javadoc) * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#channelConnected(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.ChannelStateEvent) * 建立一个新channel */ @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { log.debug("进来一个channel:" + ctx.getChannel().getId()); MessageQueue messageQueue = new MessageQueue( new ConcurrentLinkedQueue<GameRequest>()); handlerDispatcher.addMessageQueue(ctx.getChannel().getId(), messageQueue); } /* (non-Javadoc) * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#channelDisconnected(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.ChannelStateEvent) * 玩家主动关闭channel */ @Override public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { log.error("关掉一个channel:" + ctx.getChannel().getId()); handlerDispatcher.removeMessageQueue(e.getChannel().getId().toString()); e.getChannel().close(); } /* (non-Javadoc) * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#exceptionCaught(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.ExceptionEvent) * 玩家被动关闭channel */ @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { log.error("出异常啦……" + ctx.getChannel().getId()); e.getCause().printStackTrace(); handlerDispatcher.removeMessageQueue(e.getChannel().getId().toString()); e.getChannel().close(); } /* (non-Javadoc) * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#messageReceived(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.MessageEvent) * 消息接收处理器 */ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { ChannelBuffer buffs = (ChannelBuffer) e.getMessage(); buffs.skipBytes(4);// 越过dataLength的字节 byte[] decoded = new byte[buffs.readableBytes()]; buffs.readBytes(decoded); GameRequest gameRequest = new GameRequest(e.getChannel(), decoded); // 通知回调协议 handlerDispatcher.addMessage(gameRequest); } public HandlerDispatcher getHandlerDispatcher() { return handlerDispatcher; } public void setHandlerDispatcher(HandlerDispatcher handlerDispatcher) { ServerHandler.handlerDispatcher = handlerDispatcher; } }
需要注意的是:HandlerDispatcher是一个多线程处理器,用于处理游戏逻辑请求。这部分功能可根据用户的不同需求进行定制。
e) Encoder——消息编码器
消息编码器主要完成的是对游戏逻辑处理器返回的数据进行编码,组合成符合客户端规范的消息格式并发送。
- 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.frame.LengthFieldPrepender;
- import com.cp.netty.domain.GameResponse;
- /**
- * 作者:chenpeng
- * E-mail:46731706@qq.com
- * 创建时间:2012-7-12 上午11:43:11
- * 类说明
- */
- public class Encoder extends LengthFieldPrepender {
- public Encoder(int lengthFieldLength) {
- super(lengthFieldLength);
- }
- @Override
- protected Object encode(ChannelHandlerContext cxt, Channel channel,
- Object msg) throws Exception {
- ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(channel.getConfig().getBufferFactory());
- GameResponse response = (GameResponse) msg;
- buffer.writeInt(response.getRtMessage().length+20);
- buffer.writeInt(response.getCommondId());
- buffer.writeInt(response.getPlayerId());
- buffer.writeInt(response.getCommandType());
- buffer.writeLong(response.getTime());
- System.out.println("send message "+response.getCommondId());
- buffer.writeBytes(response.getRtObj().getBytesM());
- return buffer;
- }
- }
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.frame.LengthFieldPrepender; import com.cp.netty.domain.GameResponse; /** * 作者:chenpeng * E-mail:46731706@qq.com * 创建时间:2012-7-12 上午11:43:11 * 类说明 */ public class Encoder extends LengthFieldPrepender { public Encoder(int lengthFieldLength) { super(lengthFieldLength); } @Override protected Object encode(ChannelHandlerContext cxt, Channel channel, Object msg) throws Exception { ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(channel.getConfig().getBufferFactory()); GameResponse response = (GameResponse) msg; buffer.writeInt(response.getRtMessage().length+20); buffer.writeInt(response.getCommondId()); buffer.writeInt(response.getPlayerId()); buffer.writeInt(response.getCommandType()); buffer.writeLong(response.getTime()); System.out.println("send message "+response.getCommondId()); buffer.writeBytes(response.getRtObj().getBytesM()); return buffer; } }
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
- <bean id="serverPipelineFactory"
- class="com.cp.netty.ServerPipelineFactory"
- scope="prototype">
- <property name="serverHandler" ref="appHandler"></property>
- </bean>
- <bean id="appHandler" class="com.cp.netty.ServerHandler"
- init-method="init">
- <property name="handlerDispatcher" ref="handlerDispatcher" />
- </bean>
- <bean id="handlerDispatcher"
- class="com.cp.game.HandlerDispatcher" init-method="init"
- destroy-method="stop">
- <property name="messageExecutor">
- <bean class="com.cp.netty.domain.FiexThreadPoolExecutor"
- destroy-method="shutdown">
- <constructor-arg
- value="${app.dispatcher.pool.corePoolSize}" />
- <constructor-arg
- value="${app.dispatcher.pool.maximumPoolSize}" />
- <constructor-arg
- value="${app.dispatcher.pool.keepAliveSecond}" />
- </bean>
- </property>
- <property name="sleepTime" value="${app.dispatcher.sleepTime}" />
- <property name="handlerMap" ref="serverHandlerMapping" />
- </bean>
- <bean id="serverMainController" class="com.cp.game.ServerMainHandler"
- abstract="true">
- </bean>
- <bean id="serverHandlerMapping" class="java.util.HashMap">
- <constructor-arg>
- <map>
- <!-- 测试协议 -->
- <entry key="1000">
- <bean
- class="com.cp.game.handler.common.InitHandler"
- parent="serverMainController">
- </bean>
- </entry>
- </map>
- </constructor-arg>
- </bean>
- </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean id="serverPipelineFactory" class="com.cp.netty.ServerPipelineFactory" scope="prototype"> <property name="serverHandler" ref="appHandler"></property> </bean> <bean id="appHandler" class="com.cp.netty.ServerHandler" init-method="init"> <property name="handlerDispatcher" ref="handlerDispatcher" /> </bean> <bean id="handlerDispatcher" class="com.cp.game.HandlerDispatcher" init-method="init" destroy-method="stop"> <property name="messageExecutor"> <bean class="com.cp.netty.domain.FiexThreadPoolExecutor" destroy-method="shutdown"> <constructor-arg value="${app.dispatcher.pool.corePoolSize}" /> <constructor-arg value="${app.dispatcher.pool.maximumPoolSize}" /> <constructor-arg value="${app.dispatcher.pool.keepAliveSecond}" /> </bean> </property> <property name="sleepTime" value="${app.dispatcher.sleepTime}" /> <property name="handlerMap" ref="serverHandlerMapping" /> </bean> <bean id="serverMainController" class="com.cp.game.ServerMainHandler" abstract="true"> </bean> <bean id="serverHandlerMapping" class="java.util.HashMap"> <constructor-arg> <map> <!-- 测试协议 --> <entry key="1000"> <bean class="com.cp.game.handler.common.InitHandler" parent="serverMainController"> </bean> </entry> </map> </constructor-arg> </bean> </beans>
相关推荐
在本项目中,"springboot+netty开发简易式游戏源码"是一个使用Spring Boot和Netty框架构建的轻量级游戏服务器的示例。这个项目结合了两个强大的技术,旨在提供一个高效、可扩展的游戏后端解决方案。下面将详细阐述...
标题 "springboot+netty+mybatis+sqlserver" 涉及到的是一个使用Spring Boot、Netty、MyBatis以及SQL Server构建的项目。这个项目可能是一个高性能、轻量级的网络通信应用,利用Spring Boot的便利性和Netty的高效...
2. **Netty的高效性**:Netty是一个高性能、异步事件驱动的网络应用框架,它提供了对TCP、UDP协议的支持,适合处理大量并发连接,是网络游戏、聊天室等实时通讯场景的理想选择。 3. **整合步骤**:将Netty集成到...
Netty是一个高性能、异步事件驱动的网络应用程序框架,它非常适合用来构建WebSocket服务器。 Netty提供了WebSocketServerProtocolHandler来处理WebSocket协议,但在默认情况下,它会对接收到的数据包大小进行限制。...
1. **SpringBoot**:SpringBoot是Spring框架的简化版,它通过自动配置、起步依赖等方式,让开发者能够快速搭建应用。在“netty-im”项目中,SpringBoot负责管理整个应用的生命周期,包括启动、配置、依赖注入等。 2...
SpringBoot以其便捷的依赖管理和自动配置功能简化了Java应用的搭建和部署,而Netty则是一个高效的异步事件驱动的网络应用框架,常用于构建服务器和客户端的通信系统。 首先,我们要理解SpringBoot的核心理念。它...
首先,SpringBoot是Spring框架的一个简化版,它通过预配置各种依赖和设置,使得开发人员能够快速搭建并运行Java应用。SpringBoot的特点包括零配置、自动配置、内嵌Web服务器(如Tomcat或Jetty)以及便捷的起步依赖。...
Spring WebSocket是Spring框架提供的一套完整的WebSocket支持,它使得在Spring应用中集成WebSocket变得简单。 **一、WebSocket简介** WebSocket API设计目标是为了提供低延迟、高效率的双向通信机制。与HTTP不同,...
通过`Spring Boot`的自动化配置和依赖管理,我们可以快速搭建项目框架;利用`WebSocket`的双向通信能力,我们可以实现高效的客户端-服务器交互;而`Netty`则为这一切提供了底层的高性能网络支撑。这样的组合在实时性...
在IT领域,Spring Boot是一个非常流行的Java开发框架,它简化了Spring应用的初始搭建以及开发过程。Netty则是一个高性能、异步事件驱动的网络应用框架,常用于创建高效的服务器和客户端。本项目"SpringBoot集成netty...
SpringBoot和Netty结合使用,可以创建高效且灵活的服务器端应用。本文将深入探讨如何使用SpringBoot 2.0与Netty-socket来实现一个实时在线人数统计的功能,并涉及到WebSocket协议的相关知识。 **SpringBoot 2.0** ...
Netty作为一个高效、易用且功能强大的Java NIO框架,被广泛应用于各种分布式系统,如聊天应用、游戏服务器、流媒体服务等。而SpringBoot以其简洁的配置、快速的开发体验,成为了Java开发的首选框架之一。当Netty与...
Spring Boot 是一个轻量级的Java框架,用于简化Spring应用的初始搭建以及开发过程。 首先,我们需要在Spring Boot项目中添加Netty和WebSocket的相关依赖。在`pom.xml`文件中,引入如下依赖: ```xml <groupId>io...
【标题】"管理系统系列--JetLinks 基于Java8,Spring Boot 2.x ,WebFlux,Netty,Ve.zip"所涉及的核心技术主要包括Java 8、Spring Boot 2.x、WebFlux、Netty以及Ve框架。这些是构建高性能、可扩展的现代Web应用的关键...
无锁异步化、事件驱动架构设计的 java netty 网络编程框架; 轻量级,无需依赖任何第三方中间件或数据库就能支持集群、分布式; 适用于网络游戏服务器、物联网、内部系统及各种需要长连接的场景; 通过 ioGame 你...
Java的强大库支持,如Spring框架,可以帮助简化这些任务,提供安全性和可扩展性。 3. **Netty框架**: Netty是Java的一个高性能、异步事件驱动的网络应用框架,常用于创建高效的网络服务器。在WebSocket应用中,...
作为Java领域的网络通信库,Netty在分布式系统、微服务架构以及游戏服务器开发等领域广泛应用。《Netty权威指南》这本书是学习Netty的优秀资源,尤其适合初学者,下面将对Netty的基础概念、核心特性以及实际应用进行...
通过集成 Netty、Spring、Protobuf、WebSocket、TCP 和 UDP 等多种技术,它能够满足全球同服的需求,适用于各种类型和规模的网络游戏,无论是 H5、手游还是 PC 游戏,都能轻松应对。此外,该框架轻量级且易于使用,...
SpringBoot则是Spring框架的简化版,它极大地简化了Spring应用程序的开发过程,通过自动配置和起步依赖,让开发者能够快速搭建项目并投入开发。SpringBoot与Netty结合,可以提供稳定的服务端支持,同时利用Spring的...