`

基于netty4.0+spring的游戏完整架构

 
阅读更多
之前写过一篇和本文类似的博客,不过原博客是基于netty3.x实现的,今天整理了一份基于4.0的完整系统分享给大家,希望能对大家有所帮助。

架构细节原博客都有,请参照 http://cpjsjxy.iteye.com/blog/1587601

propholder.xml
<?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" xmlns:p="http://www.springframework.org/schema/p"
	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="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>config/properties/settings.properties</value>
			</list>
		</property>
	</bean>
	<bean id="serverInitializer" class="com.cp.netty.ServerInitializer"
		init-method="init">
		<property name="timeout" value="${app.channel.readtimeout}" />
		<property name="handlerDispatcher" ref="handlerDispatcher" />
		<property name="requestType" value="${app.requestType}" />

	</bean>

	<bean id="handlerDispatcher" class="com.cp.dispatcher.HandlerDispatcher">
		<property name="messageExecutor">
			<bean class="com.cp.domain.FiexThreadPoolExecutor"
				destroy-method="shutdown">
				<constructor-arg value="${app.handler.pool.corePoolSize}" />
				<constructor-arg value="${app.handler.pool.maximumPoolSize}" />
				<constructor-arg value="${app.handler.pool.keepAliveSecond}" />
				<constructor-arg value="${app.handler.pool.name}" />
			</bean>
		</property>
		<property name="sleepTime" value="${app.handler.sleepTime}" />
		<property name="handlerMap" ref="gameHandlerMap" />
	</bean>

	<bean id="gameHandlerMap" class="java.util.HashMap">
		<constructor-arg>
			<map>
				<entry key="999">
					<bean class="com.cp.handler.InitHandler">
					</bean>
				</entry>
			</map>
		</constructor-arg>
	</bean>

</beans>



settings.properties
app.handler.pool.corePoolSize=16
app.handler.pool.maximumPoolSize=32
app.handler.pool.keepAliveSecond=300
app.handler.pool.name=gamework
app.handler.sleepTime=10
app.channel.readtimeout = 3600
#http  socket  websocket_text  websocket_binary
app.requestType=socket



测试类
TestClient

package com.cp.test;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
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.codec.LengthFieldPrepender;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequestEncoder;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.handler.codec.http.HttpVersion;

import java.net.URI;

import com.cp.domain.ERequestType;

public class TestClient {
	public void connect(String host, int port, final ERequestType requestType)
			throws Exception {
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		String msg = "Are you ok?";
		if (ERequestType.SOCKET.equals(requestType)) {
			try {
				Bootstrap b = new Bootstrap();
				b.group(workerGroup);

				b.channel(NioSocketChannel.class).option(
						ChannelOption.TCP_NODELAY, true);
				b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
				b.handler(new ChannelInitializer<SocketChannel>() {
					@Override
					protected void initChannel(SocketChannel ch)
							throws Exception {
						ch.pipeline().addLast(
								"encode",
								new LengthFieldBasedFrameDecoder(
										Integer.MAX_VALUE, 0, 4, 0, 4));
						ch.pipeline().addLast("decode",
								new LengthFieldPrepender(4));
						ch.pipeline().addLast("handler",
								new ClientInboundHandler());
					}
				});
				ChannelFuture f = b.connect(host, port).sync();
				ByteBuf messageData = Unpooled.buffer();
				messageData.writeInt(999);
				messageData.writeInt(msg.length());
				messageData.writeBytes(msg.getBytes());
				f.channel().writeAndFlush(messageData).sync();
				f.channel().closeFuture().sync();

			} catch (Exception e) {
				e.printStackTrace();
			}

		} else if (ERequestType.HTTP.equals(requestType)) {

			Bootstrap b = new Bootstrap();
			b.group(workerGroup);
			b.channel(NioSocketChannel.class);
			b.option(ChannelOption.SO_KEEPALIVE, true);
			b.handler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {

					// 客户端接收到的是httpResponse响应,所以要使用HttpResponseDecoder进行解码
					ch.pipeline().addLast(new HttpResponseDecoder());
					// 客户端发送的是httprequest,所以要使用HttpRequestEncoder进行编码
					ch.pipeline().addLast(new HttpRequestEncoder());
					ch.pipeline().addLast(new ClientInboundHandler());

				}
			});
			ChannelFuture f = b.connect(host, port).sync();
			b.channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY,true);
			b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);

			URI uri = new URI("http://" + host + ":" + port);

			DefaultFullHttpRequest request = new DefaultFullHttpRequest(
					HttpVersion.HTTP_1_1, HttpMethod.POST, uri.toASCIIString(),
					Unpooled.wrappedBuffer(msg.getBytes("UTF-8")));

			// 构建http请求
			request.headers().set(HttpHeaders.Names.HOST, host);
			request.headers().set(HttpHeaders.Names.CONNECTION,
					HttpHeaders.Values.KEEP_ALIVE);
			request.headers().set(HttpHeaders.Names.CONTENT_LENGTH,
					request.content().readableBytes());
			// 发送http请求
			f.channel().write(request);
			f.channel().flush();
			f.channel().closeFuture().sync();
		}

		try {
		} finally {
			workerGroup.shutdownGracefully();
		}

	}

	public static void main(String[] args) throws Exception {
		TestClient client = new TestClient();
		client.connect("127.0.0.1", 8080, ERequestType.SOCKET);
	}
}



ClientInboundHandler
package com.cp.test;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponse;

public class ClientInboundHandler extends ChannelInboundHandlerAdapter {

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		if (msg instanceof HttpResponse) {
			HttpResponse response = (HttpResponse) msg;
			System.out.println("CONTENT_TYPE:"
					+ response.headers().get(HttpHeaders.Names.CONTENT_TYPE));
		}
		if (msg instanceof HttpContent) {
			HttpContent content = (HttpContent) msg;
			ByteBuf buf = content.content();
			System.out.println(buf.toString(io.netty.util.CharsetUtil.UTF_8));
			buf.release();
		}
		if (msg instanceof ByteBuf) {
			ByteBuf messageData = (ByteBuf) msg;
			int commandId = messageData.readInt();
			int length = messageData.readInt();
			byte[] c = new byte[length];
			messageData.readBytes(c);
			System.out.println("commandId:"+commandId+"\tmessage:"+new String(c));
		}
	}
}


本测试代码已经过http、socket、websocket测试。

鉴于很多朋友想深入交流,特提供源码demo项目下载地址:
https://github.com/pofuchenzhou/netty-spring-game.git
分享到:
评论
13 楼 cpjsjxy 2016-05-17  
185248148 写道
没原码啊,,,

https://github.com/pofuchenzhou/netty-spring-game
12 楼 185248148 2016-05-05  
没原码啊,,,
11 楼 cpjsjxy 2016-01-21  
roway 写道
weiluo12@126.com求源码,谢谢!!!

https://github.com/pofuchenzhou/netty-spring-game
10 楼 roway 2016-01-21  
weiluo12@126.com求源码,谢谢!!!
9 楼 zcqshine 2015-09-06  
OK 了, 基于 netty5.0的 socket 请求方式调通过了. 谢谢博主
8 楼 zcqshine 2015-09-02  
请教下博主. 反编译了你的 jar 包后, 在有 switch 的地方反编译出来的语句很奇怪, 能提供下 command 类的源码吗, 还有 ERequest 这个枚举类里的请求类型的顺序是否为SOCKET("socket"), HTTP("http"), WEBSOCKET_TEXT("websocket_text"), WEBSOCKET_BINARY("websocket_binary")
如果是按照这个顺序来的话, 那么根据反编译出来的 command 类里的 switch 语句里的逻辑好像有问题.
7 楼 zcqshine 2015-09-02  
TestClient 类84行的代码要修改, 要删掉".channel(NioSocketChannel.class)"这部分, 因为在69行处已经设置过channelFactory了, 否则运行的时候会报错:java.lang.IllegalStateException: channelFactory set already.

对了, 我用的是 netty5.0
6 楼 kenjianyin 2015-04-27  
楼主,求源码~谢谢
5 楼 ketzi 2015-01-28  
socket,websocket可以使用同一个端口不?
4 楼 cpjsjxy 2014-11-26  
web_dig 写道
2593399875@qq.com 谢谢


反编译自己看吧
3 楼 web_dig 2014-11-21  
2593399875@qq.com 谢谢
2 楼 web_dig 2014-11-21  
楼主,求源码。
1 楼 yexiaoxiao1991 2014-11-13  
                 

相关推荐

    基于netty+websocket+springboot的实时聊天系统项目源码.zip

    1、基于netty+websocket+springboot的实时聊天系统项目源码.zip 2、该资源包括项目的全部源码,下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料...

    基于springcloud+Netty+MQ+mysql的分布式即时聊天系统.zip

    基于springcloud+Netty+MQ+mysql的分布式即时聊天系统.zip基于springcloud+Netty+MQ+mysql的分布式即时聊天系统.zip基于springcloud+Netty+MQ+mysql的分布式即时聊天系统.zip基于springcloud+Netty+MQ+mysql的分布式...

    毕设项目:基于netty+websocket+springboot的实时聊天系统.zip

    毕设项目:基于netty+websocket+springboot的实时聊天系统 毕设项目:基于netty+websocket+springboot的实时聊天系统 毕设项目:基于netty+websocket+springboot的实时聊天系统 毕设项目:基于netty+websocket+...

    Netty+Spring Boot仿微信 全栈开发高性能后台及客户端

    本项目"Netty+Spring Boot仿微信 全栈开发高性能后台及客户端"旨在教你如何利用Netty和Spring Boot这两个强大的技术栈来实现类似微信的应用。接下来,我们将深入探讨这两个技术以及它们在全栈开发中的应用。 1. ...

    netty+spring服务端-omen-1.1

    omen-1.1 自己基于netty开发的服务端,支持spring配置服务器启动模式:http,tcp,websocket等,并支持NIO和OIO方式,项目已应用于生产,可以通过jar形式加入其它项目,业务类实现业务service,启动不依赖于其他应用...

    基于springcloud+Netty+MQ+mysql的分布式即时聊天系统源码+项目说明(毕业设计).zip

    基于springcloud+Netty+MQ+mysql的分布式即时聊天系统源码+项目说明(毕业设计).zip 1、该资源内项目代码经过严格调试,下载即用确保可以运行! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、...

    Springboot 2.0 整合 Netty 4.0 实现IO异步通讯架构

    Springboot2.0.8集成 netty4 ,使用protobuf作为ping的数据交换,比json更加的小巧,占用数据量更小,可用于任何第三方应用做心跳监控。 已完成功能: - 客户端授权验证(基于protoBuff) - 心跳检测(基于protoBuff) ...

    一款基于Netty+Zookeeper+Spring实现的轻量级Java RPC框架。提供服务注册,发现,负载均衡,.zip

    标题中的“一款基于Netty+Zookeeper+Spring实现的轻量级Java RPC框架”揭示了这个项目的核心技术栈,它整合了三个在分布式系统中广泛使用的开源库:Netty、Zookeeper和Spring。让我们逐一深入探讨这三个技术以及它们...

    基于springboot+netty+vue构建的类似bililbili的弹幕群聊系统,个人娱乐项目,可用于前后端开发学习研究

    基于springboot+netty+vue构建的类似bililbili的弹幕群聊系统,个人娱乐项目,可用于前后端开发学习研究 基于springboot+netty+vue构建的类似bililbili的弹幕群聊系统,个人娱乐项目,可用于前后端开发学习研究 ...

    Netty4.0 jar包 及 源代码 和 例子

    Netty4.0全部jar包.开发时候只需要倒入总的哪一个netty4.0.jar就行了 后缀为resources.jar的全部是源码。 简单的代码例子在netty-example-resources.jar里面。

    netty4.0文件分片上传+断点续传+权限校验

    在本文中,我们将深入探讨如何利用Netty 4.0实现文件分片上传、断点续传以及权限校验的功能。 **文件分片上传** 文件分片上传是为了处理大文件传输时,避免一次性加载整个文件到内存中,从而减少内存消耗和提高...

    1078解析推流源代码(netty+javacv+spring+maven+rtp+rtmp)

    【标题】"1078解析推流源代码(netty+javacv+spring+maven+rtp+rtmp)" 涉及的关键技术是网络编程、视频处理和流媒体服务,下面将详细介绍这些领域的相关知识。 【Netty】 Netty 是一个高性能、异步事件驱动的网络...

    基于springcloud+Netty+MQ+mysql的分布式即时聊天系统完整源码+数据库+说明.zip

    【资源说明】 1、该资源内项目代码都是经过测试运行成功,功能正常的情况下才上传的,请放心下载使用。 2、适用人群:主要针对计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、...

    resteasy使用netty

    Netty的优势在于它的非阻塞I/O模型和事件驱动架构。通过使用NIO(Non-blocking I/O),Netty可以在单个线程中处理多个连接,从而提高了并发性能。此外,Netty提供了高度定制化的ChannelHandler,允许开发者灵活地...

    使用netty+spring搭建游戏框架

    综上所述,搭建一个Netty+Spring的游戏框架需要理解两个框架的核心原理,并将其特性融合到游戏服务的各个层面。通过这样的框架,可以构建出稳定、高效的网络游戏服务器。如果你对这个主题感兴趣,可以参考给定的博文...

    netty源码+Spring源码视频教程.txt

    根据提供的文件信息,我们可以推断出这是一份包含Netty和Spring框架源码学习资源的教程文档。尽管链接部分无法直接解析为具体内容,但可以基于标题、描述以及标签中的信息来构建相关的知识点。 ### Netty源码分析 ...

    Spring+Netty+WebSocket实例

    在现代Web开发中,实时通信已经成为一个不可或缺的功能,Spring、Netty和WebSocket的结合为构建高性能、低延迟的实时应用提供了强大的解决方案。本实例将详细探讨如何利用这三种技术进行集成,实现高效的双向通信。 ...

Global site tag (gtag.js) - Google Analytics