第一个版本实现面向字符串的TCP长连接服务
看点:Liunx优化、TCP连接设置
public static void main(String[] argv) throws Exception{
EventLoopGroup bossLoop = new NioEventLoopGroup(); //接收消息循环队列
EventLoopGroup workerLoop = new NioEventLoopGroup(); //发送消息循环队列
try{
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossLoop, workerLoop) //加载消息循环队列
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
.option(ChannelOption.TCP_NODELAY, true); //TCP立即发包
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
// TODO Auto-generated method stub
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder()); //Netty4自带的String解码器
pipeline.addLast(new StringEncoder()); //Netty4自带的String编码器
pipeline.addLast(new MyHandler()); // 自己实现的处理器
}
});
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture future = bootstrap.bind(port).sync();
if (future.isSuccess()){}
future.channel().closeFuture().sync();
} catch (Exception e) {
} finally {
workerLoop.shutdownGracefully();
bossLoop.shutdownGracefully();
}
}
file:MyHandler.java
public class ProtoBufHandler extends SimpleChannelInboundHandler<Protocol> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
ctx.writeAndFlush(msg);
ctx.close();
}
}String osName = System.getProperty("os.name");
EventLoopGroup bossLoop = null;
EventLoopGroup workerLoop = null;
if (osName.equals("Linux")) {
bossLoop = new EpollEventLoopGroup();
workerLoop = new EpollEventLoopGroup();
} else {
bossLoop = new NioEventLoopGroup();
workerLoop = new NioEventLoopGroup();
}
if (osName.equals("Linux")) { //Linux平台用Epoll模式
bootstrap.channel(EpollServerSocketChannel.class);
} else {
bootstrap.channel(NioServerSocketChannel.class);
}
很多文章一股脑把tcp连接属性都加上了,其实很多是不必要的,例如keepAlive。常用的如下:
bootstrap.group(bossLoop, workerLoop)
//keepAlive默认是打开
//.option(ChannelOption.SO_KEEPALIVE, true)
// 默认采用AdaptiveRecvByteBufAllocator分配器,不需要配置
//.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT)
//PooledByteBufAllocator这种分配器是默认分配器,当buffer被写入下一个节点的时候,它会
//自动释放,并放入pool里面
//.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
.option(ChannelOption.SO_SNDBUF, 1024*256) //发包缓冲区,单位多少?
.option(ChannelOption.SO_RCVBUF, 1024*256) //收包换成区,单位多少?
.option(ChannelOption.TCP_NODELAY, true); //TCP立即发包