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

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

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

propholder.xml


	
		
			
				config/properties/settings.properties
			
		
	
	
		
		
		

	

	
		
			
				
				
				
				
			
		
		
		
	

	
		
			
				
					
					
				
			
		
	





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() {
					@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() {
				@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
  • netty-gamework-1.0.0.jar (28.8 KB)
  • 下载次数: 1143

你可能感兴趣的:(基于netty4.0+spring的游戏完整架构)