1. 程式人生 > >Netty學習之分隔符解決TCP粘包

Netty學習之分隔符解決TCP粘包

package com.phei.netty.s20160424;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
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;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
/**
 * 服務端
 * @author renhj
 *
 */
public class TimeServer {

	public void bind(int port) throws Exception{
		
		//第一個使用者伺服器接收客戶端的連線
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		//第二個使用者SocketChannel的網路讀寫
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
         //建立ServerBootstrap物件,啟動 NIO服務端的輔助啟動類
      	 ServerBootstrap b = new ServerBootstrap();
      	 b.group(bossGroup, workerGroup).
      	 //設定為NIO
      	 channel(NioServerSocketChannel.class)
      	 .option(ChannelOption.SO_BACKLOG, 1024)
      	 .handler(new LoggingHandler(LogLevel.INFO))
      	 .childHandler(new ChildChannelHandler());
      	  
      	 //繫結埠,同步等待成功
      	 ChannelFuture f = b.bind(port).sync();
      	 
         //等待伺服器監聽埠關閉
      	 f.channel().closeFuture().sync();
      	 
        }finally{
      	 //釋放執行緒池資源
         bossGroup.shutdownGracefully();
         workerGroup.shutdownGracefully();
        }
		
	}
	
	private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{
		
		@Override
		protected void initChannel(SocketChannel arg0) throws Exception {
			//解決TCP粘包問題,以"$_"作為分隔
			ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
			arg0.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,delimiter));
			arg0.pipeline().addLast(new StringDecoder());
			
			arg0.pipeline().addLast(new TimeServerHandler());
			
		}
	}
	
	public static void main(String[] args) throws Exception {
		
		int port = 8080;
		if(args != null && args.length>0){
			try{
				port = Integer.valueOf(args[0]);
			}catch(Exception e){
				//採用預設值
			}
		}
		new TimeServer().bind(port);
	}

}