1. 程式人生 > >Netty學習(3): 客戶端和服務端的例子

Netty學習(3): 客戶端和服務端的例子

服務端:

package com.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
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.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * 服務端
 * 
 * @author xiajie
 *
 */
public class Server {

	public static void main(String[] args) {
		/**
		 * 服務啟動類
		 */
		ServerBootstrap bootstrap = new ServerBootstrap();
		
		/**
		 * boss和worker
		 * 這兩個可以理解為執行緒池,EventLoopGroup內部是對執行緒池的封裝
		 */
		EventLoopGroup boss = new NioEventLoopGroup();
		EventLoopGroup worker = new NioEventLoopGroup();
		
		try {
			//設定執行緒池
			bootstrap.group(boss, worker);
			
			//設定socket工廠、
			bootstrap.channel(NioServerSocketChannel.class);
			
			//設定管道工廠
			bootstrap.childHandler(new ChannelInitializer<Channel>() {

				/**
				 * 管道最終要設定到處理器中
				 */
				@Override
				protected void initChannel(Channel ch) throws Exception {
					/**
					 * 設定解碼處理器
					 */
					ch.pipeline().addLast(new StringDecoder());
					/**
					 * 設定編碼處理器
					 */
					ch.pipeline().addLast(new StringEncoder());
					ch.pipeline().addLast(new ServerHandler());
				}
			});
			

			//設定引數,TCP引數
			bootstrap.option(ChannelOption.SO_BACKLOG, 2048);//serverSocketchannel的設定,連結緩衝池的大小
			bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);//socketchannel的設定,維持連結的活躍,清除死連結
			bootstrap.childOption(ChannelOption.TCP_NODELAY, true);//socketchannel的設定,關閉延遲傳送
			
			//繫結埠
			ChannelFuture future = bootstrap.bind(10201);
			
			System.out.println("start");
			
			//等待服務端關閉
			future.channel().closeFuture().sync();
			
		} catch (Exception e) {
			e.printStackTrace();
			System.out.print(e);
		} finally{
			//釋放資源
			boss.shutdownGracefully();
			worker.shutdownGracefully();
		}
	}
}
package com.server;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
 * 服務端訊息處理
 * @author xiajie
 *
 */
public class ServerHandler extends SimpleChannelInboundHandler<String> {

	/**
	 * 訊息接收處理方法
	 */
	@Override
	protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {

		System.out.println("服務端收到"+ctx.channel().remoteAddress()+"發來的訊息:"+msg);
		ctx.channel().writeAndFlush("hi 服務已經收到你IP="+ctx.channel().remoteAddress()+"發的訊息");
		ctx.writeAndFlush("hi 服務已經收到你發的訊息");
	}

	/**
	 * 當有新的客戶端連線到服務端
	 */
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		System.out.println("channelActive.......新的客戶端連線到服務端");
	}

	/**
	 * 當客戶端斷開與服務端的連線
	 */
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		System.out.println("channelInactive.......客戶端斷開與服務端的連線");
	}

	/**
	 * 異常
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
	}
	
	
}

客戶端

package com.client;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * netty的客戶端
 * @author xiajie
 *
 */
public class Client {

	public static void main(String[] args) {
		//服務類
		Bootstrap bootstrap = new Bootstrap();
		
		//worker
		EventLoopGroup worker = new NioEventLoopGroup();
		
		try {
			//設定執行緒池
			bootstrap.group(worker);
			
			//設定socket工廠、
			bootstrap.channel(NioSocketChannel.class);
			
			//設定管道
			bootstrap.handler(new ChannelInitializer<Channel>() {

				@Override
				protected void initChannel(Channel ch) throws Exception {
					ch.pipeline().addLast(new StringDecoder());
					ch.pipeline().addLast(new StringEncoder());
					ch.pipeline().addLast(new ClientHandler());
				}
			});
			
			ChannelFuture connect = bootstrap.connect("127.0.0.1", 10201);
			
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
			while(true){
				System.out.println("請輸入:");
				String msg = bufferedReader.readLine();
				connect.channel().writeAndFlush(msg);
			}
			
		} catch (Exception e) {
			 e.printStackTrace();
		} finally{
			worker.shutdownGracefully();
		}
	}
}
package com.client;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

/**
 * 客戶端訊息處理
 * @author xiajie
 *
 */
public class ClientHandler extends SimpleChannelInboundHandler<String> {

	@Override
	protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
		System.out.println("客戶端收到訊息:"+msg);
	}

}

執行結果