一直从事的java web方面的开发,最近想去深圳了,据说那里做游戏服务的很多,就学习一下nio框架netty。
一、 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应用教程,将在其他文章中有所提及,敬请关注!
三、开始写游戏服务
maven依赖如下
<ependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency>
服务入口
public class GameServer {
public void bind(int port) throws Exception
{
EventLoopGroup bossGroup = new NioEventLoopGroup();//线程组
EventLoopGroup workGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();//server启动管理配置
b.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 2048)//最大客户端连接数为2048
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ServerHandler());//服务端业务处理handler
// ch.pipeline().addLast(new LengthDecoder(1024,0,4,0,4));
// ch.pipeline().addLast(new MessageDecoder());
// ch.pipeline().addLast(new MessageEncoder());
}
});
ChannelFuture f = b.bind(port).sync();
if (f.isSuccess())
{
System.out.println("Server starts success at port:" + port);
}
f.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
}finally{
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception
{
int port = 8012;
new GameServer().bind(port);
}
}
服务端页面处理handler
public class ServerHandler extends ChannelHandlerAdapter{
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception //当客户端连上服务器的时候会触发此函数
{
System.out.println("clinet编号:" + ctx.channel().id() + "加入服务器");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception//当客户端断开连接的时候触发函数
{
System.out.println("clinet:" + ctx.channel().id() + " 离开服务器");
//User.onlineUser.remove(LoginDispatch.getInstance().user);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{//服务端接受客户端数据
ByteBuf buf = (ByteBuf) msg;
String rev = getMessage(buf);
System.out.println("服务端收到客户端数据:" + rev);
String messgae="我收到了,apple给你,succcess";
try {
ctx.writeAndFlush(getSendByteBuf(messgae));//返回给客户端数据
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// SocketModel message = (SocketModel) msg;
// //当客户端发送数据到服务器会触发此函数,消息分发
// switch (message.getType()) {
// case 1:
// LoginDispatch.getInstance().dispatch(ctx, message);//分派登录消息
// break;
// default:
// break;
// }
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
{
//cause.printStackTrace();
}
private String getMessage(ByteBuf buf) {
byte[] con = new byte[buf.readableBytes()];
buf.readBytes(con);
try {
return new String(con, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
private ByteBuf getSendByteBuf(String message)
throws UnsupportedEncodingException {
byte[] req = message.getBytes("UTF-8");
ByteBuf pingMessage = Unpooled.buffer();
pingMessage.writeBytes(req);
return pingMessage;
}
}
接下来启动gameserver,控制台输入如下
Server starts success at port:8012