handler?.let { logInfo(logger,"找到照应指令的 Handler: ${it.javaClass.simpleName}")
it.channelRead(ctx, msg) } ?: logInfo(logger,"未找到照应指令的 Handler")
} @Throws(Exception::class)
override fun channelInactive(ctx: ChannelHandlerContext) {
val insocket = ctx.channel().remoteAddress() as InetSocketAddress
val clientIP = insocket.address.hostAddress
val clientPort = insocket.port
logError(logger,"客户端掉线: $clientIP : $clientPort")
super.channelInactive(ctx)
}}
四. TCP 客户端
模拟一个客户端的完成
val topLevelClass = object : Any() {}.javaClass.enclosingClass
val logger: Logger = LoggerFactory.getLogger(topLevelClass)fun main() {
val worker = NioEventLoopGroup()
val bootstrap = Bootstrap()
bootstrap.group(worker).channel(NioSocketChannel::class.java)
.handler(object : ChannelInitializer<SocketChannel>() {
@Throws(Exception::class)
override fun initChannel(channel: SocketChannel) {
channel.pipeline().addLast(PacketCodecHandler) channel.pipeline().addLast(ClientIdleHandler()) channel.pipeline().addLast(ClientLogin()) } }) val future: ChannelFuture = bootstrap.connect("127.0.0.1", TCP_PORT).addListener(object : ChannelFutureListener {
@Throws(Exception::class)
override fun operationComplete(channelFuture: ChannelFuture) {
if (channelFuture.isSuccess()) {
logInfo(logger,"connect to server success!")
} else {
logger.info("failed to connect the server! ")
System.exit(0)
} } }) try {
future.channel().closeFuture().sync() logInfo(logger,"与效劳端断开衔接!")
} catch (e: InterruptedException) {
e.printStackTrace() }}
其中,PacketCodecHandler 跟效劳端运用的解析报文的 Handler 是一样的。
ClientIdleHandler:客户端完成心跳,每隔 30 秒发送一次心跳。
class ClientIdleHandler : IdleStateHandler(0, 0, HEART_BEAT_TIME) {
private val logger = LoggerFactory.getLogger(ClientIdleHandler::class.java)
@Throws(Exception::class)
override fun channelIdle(ctx: ChannelHandlerContext, evt: IdleStateEvent?) {
logInfo(logger,"发送心跳....")
ctx.writeAndFlush(HeartBeatPacket()) } companion object {
private const val HEART_BEAT_TIME = 30
}}
ClientLogin:登录效劳端的 Handler。
@ChannelHandler.Sharable
(责任编辑:admin)