Skip to content

Instantly share code, notes, and snippets.

@aaronzirbes
Created April 28, 2017 20:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aaronzirbes/6641e29bf09f747c9c5d12b07637badd to your computer and use it in GitHub Desktop.
Save aaronzirbes/6641e29bf09f747c9c5d12b07637badd to your computer and use it in GitHub Desktop.
Basic Netty TCP server
package org.zirbes.sandbox
import groovy.util.logging.Slf4j
import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInboundHandlerAdapter
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.NioServerSocketChannel
@Slf4j
class MockTcpServer {
protected final int port
protected ChannelFuture channel
protected final EventLoopGroup masterGroup = new NioEventLoopGroup()
protected final EventLoopGroup workerGroup = new NioEventLoopGroup()
MockTcpServer(int port) {
this.port = port
}
void run() {
log.info "Starting MockTcpServer service on port=${port}"
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
void run() { shutdown() }
})
try {
final ServerBootstrap bootstrap = new ServerBootstrap()
.group(masterGroup, workerGroup)
.channel(NioServerSocketChannel)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
void initChannel(final SocketChannel ch) throws Exception {
ch.pipeline().addLast("request",
new ChannelInboundHandlerAdapter() {
@Override
void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String base64Bytes = msg.toString().bytes.encodeBase64()
log.info "Received request of type=${msg.class} bytes=${base64Bytes}"
final byte[] response = 'Hello.'.bytes
ctx.writeAndFlush(response)
}
@Override
void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush()
}
@Override
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
log.error 'Something went wrong.', cause
}
})
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true)
log.info "Starting MockTcpServer service on port=${port}"
channel = bootstrap.bind(port).sync()
log.info "Shutting down MockTcpServer service on port=${port}"
} catch (final InterruptedException e) {
log.warn "Shutting down MockTcpServer service on port=${port} due to interruption"
}
}
void shutdown() {
workerGroup.shutdownGracefully()
masterGroup.shutdownGracefully()
try {
channel.channel().closeFuture().sync()
} catch (InterruptedException e) {
log.error "Shutting down MockTcpServer service on port=${port} due failed"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment