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