java游戏服务器开发之八-网络事件监听器
网络事件监听器,将网络变化交由NetworkListener处理
可以看到,我们现在所有的逻辑都是写在TcpMessageStringHandler里面,
我们可以使用创建一个类,用于监听网络的变化,NetworkListener
还有一个类用于处理发送上来的信息(可查看后面博客)
首先,先创建一个接口INetworkEventListener,里面包含3个方法,onConnected/onDisconnected/onExceptionCaught,看名称其实也能知道这几个方法,"连接建立/连接断开/异常发生"。
然后,写个实现类NetworkListener,刚开始没有什么逻辑,我们就分别在三种情况发生的时候进行下日志打印。
接着,将NetworkListener注入到TcpMessageStringHandler,使用Autowired注解,如下
@Autowired
private INetworkEventListener listener;
这样这三种情况各自对应netty提供的channelActive/channelInactive/exceptionCaught中,这样监听方式就可以了。
最后在TcpServerStringInitializer中获取TcpMessageStringHandler的时候就不能直接使用new的方式了,需要通过getBean方式获取
TcpMessageStringHandler tcpMessageStringHandler = (TcpMessageStringHandler) ServerConfig.getInstance().getApplicationContext()
.getBean("tcpMessageStringHandler");
pipeline.addLast(tcpMessageStringHandler);
注意几个东西,1.NetworkListener只需使用单例模式,没有必要一个请求对应一个
2.TcpMessageStringHandler需要分别对应不同的客户端连接
@Scope("singleton")这个注解表示这个类交由spring 管理的时候,每次使用getBean,都会是用一个对象,如NetworkListener
@Scope("prototype")这个注解表示这个类交由spring 管理的时候,每次使用getBean,都会重新生成一个对象,如TcpMessageStringHandler
现在看各自的代码:
INetworkEventListener
/** * Copyright (C), 2015-2018 * FileName: INetworkEventListener * Author: zhao * Date: 2018/6/22 10:46 * Description: 网络事件监听 * History: * <author> <time> <version> <desc> * 作者姓名 修改时间 版本号 描述 */ package com.lizhaoblog.base.network.listener; import io.netty.channel.ChannelHandlerContext; /** * 〈一句话功能简述〉<br> * 〈网络事件监听〉 * * @author zhao * @date 2018/6/22 10:46 * @since 1.0.0 */ public interface INetworkEventListener { /** * 连接建立 * * @param ctx ChannelHandlerContext */ void onConnected(ChannelHandlerContext ctx); /** * 连接断开 * * @param ctx ChannelHandlerContext */ void onDisconnected(ChannelHandlerContext ctx); /** * 异常发生 * * @param ctx ChannelHandlerContext * * @param throwable 异常 */ void onExceptionCaught(ChannelHandlerContext ctx, Throwable throwable); }
NetworkListener
/** * Copyright (C), 2015-2018 * FileName: NetworkListener * Author: zhao * Date: 2018/6/22 10:52 * Description: 网络事件监听器,实现类 * History: * <author> <time> <version> <desc> * 作者姓名 修改时间 版本号 描述 */ package com.lizhaoblog.server.core.listener; import com.lizhaoblog.base.network.listener.INetworkEventListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import io.netty.channel.ChannelHandlerContext; /** * 〈一句话功能简述〉<br> * 〈网络事件监听器,实现类〉 * * @author zhao * @date 2018/6/22 10:52 * @since 1.0.0 */ @Component @Scope("singleton") public class NetworkListener implements INetworkEventListener { private static final Logger logger = LoggerFactory.getLogger(NetworkListener.class); @Override public void onConnected(ChannelHandlerContext ctx) { logger.info("建立连接"); } @Override public void onDisconnected(ChannelHandlerContext ctx) { logger.info("连接断开"); } @Override public void onExceptionCaught(ChannelHandlerContext ctx, Throwable throwable) { logger.debug("异常发生", throwable); } }TcpMessageStringHandler
/** * Copyright (C), 2015-2018 * FileName: TcpMessageStringHandler * Author: zhao * Date: 2018/6/12 15:01 * Description: tcp消息处理 * History: * <author> <time> <version> <desc> * 作者姓名 修改时间 版本号 描述 */ package com.lizhaoblog.server.channel.tcp.str; import com.lizhaoblog.base.network.listener.INetworkEventListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; /** * 〈一句话功能简述〉<br> * 〈tcp消息处理〉 * * @author zhao * @date 2018/6/12 15:01 * @since 1.0.0 */ @Component @Scope("prototype") public class TcpMessageStringHandler extends SimpleChannelInboundHandler<String> { private static final Logger logger = LoggerFactory.getLogger(TcpMessageStringHandler.class); @Autowired private INetworkEventListener listener; @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) { logger.info("数据内容:data=" + msg); String result = "小李,我是服务器,我收到你的信息了。"; logger.info("this is " + this); logger.info("listener is " + listener); ctx.writeAndFlush(result); } @Override public void channelActive(ChannelHandlerContext ctx) { listener.onConnected(ctx); } @Override public void channelInactive(ChannelHandlerContext ctx) { listener.onDisconnected(ctx); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) { listener.onExceptionCaught(ctx, throwable); } }TcpServerStringInitializer
/** * Copyright (C), 2015-2018 * FileName: TcpServerStringInitializer * Author: zhao * Date: 2018/6/12 15:00 * Description: TcpServerInitializer请求处理器 * History: * <author> <time> <version> <desc> * 作者姓名 修改时间 版本号 描述 */ package com.lizhaoblog.server.channel.tcp.str; import com.lizhaoblog.base.network.listener.INetworkEventListener; import com.lizhaoblog.server.pojo.ServerConfig; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; /** * 〈一句话功能简述〉<br> * 〈TcpServerInitializer请求处理器〉 * * @author zhao * @date 2018/6/12 15:00 * @since 1.0.0 */ @Component public class TcpServerStringInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); TcpMessageStringHandler tcpMessageStringHandler = (TcpMessageStringHandler) ServerConfig.getInstance().getApplicationContext() .getBean("tcpMessageStringHandler"); pipeline.addLast(tcpMessageStringHandler); } }
上面的代码在码云上 https://gitee.com/lizhaoandroid/JgServer
可以加qq群一起探讨Java游戏服务器开发的相关知识 676231524