netty3.0的服务端及客户端的搭建

不喜欢写描述什么的,基本上使用步骤,注意事项都在代码注释中标明了,而相关的内容网上有很多,比自己的理解更好,所以自己对某个知识点的理解则都写在了为知笔记中。

1、服务端的编写

package com.netty.helloserver;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

/**
 * @author Chalmers 2016年2月18日 下午6:49:57
 */
public class NettyServer {

	public static void main(String[] args) {
		// 创建服务类对象
		ServerBootstrap serverBootstrap = new ServerBootstrap();
		// 创建两个线程池
		// 简单来讲,就是boss监听端口,worker来监听selector(NIO里面的)
		ExecutorService boss = Executors.newCachedThreadPool();
		ExecutorService worker = Executors.newCachedThreadPool();
		// 设置工厂,并且把两个线程池加入进去
		// 经测试,该方法在netyy3.0中有效,5.0中没有
		serverBootstrap.setFactory(new NioServerSocketChannelFactory(boss,
				worker));
		// 设置管道工厂
		serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {

			@Override
			public ChannelPipeline getPipeline() throws Exception {

				ChannelPipeline channelPipeline = Channels.pipeline();
				// 加上此行代码,在Handler中便可以直接获取字符串,而不用经过ChannelBuffer了
				// 看源码可得,decoder用来处理上行数据
				channelPipeline.addLast("decoder", new StringDecoder());
				// encoder用来数据下行数据
				channelPipeline.addLast("encoder", new StringEncoder());
				/**
				 * 经测试可得,decoder和encoder不能省去,而下面的可以省掉
				 */
				channelPipeline.addLast("helloHandler", new ServerHandler());
				// 返回
				return channelPipeline;
			}
		});

		// 注意此行代码,在绑定时,一定要在工厂之后,否则就会报错
		serverBootstrap.bind(new InetSocketAddress(9090));
		System.out.println("start --> server");

	}
}

class ServerHandler extends SimpleChannelHandler {

	/**
	 * 不管是否已经连接,都将执行
	 */
	@Override
	public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		super.channelClosed(ctx, e);
		System.out.println("channelClosed");
	}

	/**
	 * 当网络连接时执行
	 */
	@Override
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		super.channelConnected(ctx, e);
		System.out.println("channelConnected");
	}

	/**
	 * 只有当网络连接过,断开时才会执行
	 */
	@Override
	public void channelDisconnected(ChannelHandlerContext ctx,
			ChannelStateEvent e) throws Exception {
		super.channelDisconnected(ctx, e);
		System.out.println("channelDisconnected");
	}

	/**
	 * 捕获异常
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
		super.exceptionCaught(ctx, e);
		System.out.println("exceptionCaught");
	}

	/**
	 * 接收消息
	 */
	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
			throws Exception {
		super.messageReceived(ctx, e);
		System.out.println("messageReceived");
		// 因为在设置管道工厂时,设置了StringDecode,所以在此时可以直接获得
		// 但如果没有设置的话,可以通过以下方法
		// ChannelBuffer message = (ChannelBuffer) e.getMessage();
		// System.out.println(new String(message.array()));

		System.out.println(e.getMessage());

		/*
		 * 发送消息
		 */
		// ChannelBuffer copiedBuffer = ChannelBuffers.copiedBuffer("hi"
		// .getBytes());
		// ctx.getChannel().write(copiedBuffer);

		// 因为在管道中设置了encoder,所以可以像读取一样,写成下面的形式
		ctx.getChannel().write("hi");
	}

}

2、客户端的编写

package com.netty.hiclient;

import java.net.InetSocketAddress;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

/**
 * @author Chalmers 2016年2月18日 下午10:22:08
 */
public class NettyClient {

	private static ClientBootstrap clientBootstrap;

	public static void main(String[] args) {
		// 获得客户端对象
		clientBootstrap = new ClientBootstrap();

		// 创建两个线程池
		ExecutorService boss = Executors.newCachedThreadPool();
		ExecutorService worker = Executors.newCachedThreadPool();

		// 设置工厂,跟服务端一样
		clientBootstrap.setFactory(new NioClientSocketChannelFactory(boss,
				worker));
		// 设置管道工厂
		clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() {

			@Override
			public ChannelPipeline getPipeline() throws Exception {
				ChannelPipeline channelPipeline = Channels.pipeline();
				// 进行包装
				channelPipeline.addLast("decoder", new StringDecoder());
				channelPipeline.addLast("encoder", new StringEncoder());
				channelPipeline.addLast("hiHandler", new ClientHandler());
				return channelPipeline;
			}
		});

		System.out.println("start --> client");
		// 一定记住,这个地方用的是connect,而不是bind
		ChannelFuture channelFuture = clientBootstrap
				.connect(new InetSocketAddress("127.0.0.1", 9090));
		// 可以冲future中获得channel
		Channel channel = channelFuture.getChannel();
		Scanner sc = new Scanner(System.in);
		while (true) {
			System.out.print("输入: ");
			// 用获得channel进行输出
			channel.write(sc.next());
		}
	}
}

class ClientHandler extends SimpleChannelHandler {

	@Override
	public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		super.channelClosed(ctx, e);
		System.out.println("channelClosed");
	}

	@Override
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		super.channelConnected(ctx, e);
		System.out.println("channelConnected");
	}

	@Override
	public void channelDisconnected(ChannelHandlerContext ctx,
			ChannelStateEvent e) throws Exception {
		super.channelDisconnected(ctx, e);
		System.out.println("channelDisconnected");
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
		super.exceptionCaught(ctx, e);
		System.out.println("exceptionCaught");
	}

	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
			throws Exception {
		super.messageReceived(ctx, e);
		System.out.println("messageReceived");
		System.out.println(e.getMessage());
	}

}

猜你喜欢

转载自moonmonster.iteye.com/blog/2278672