服务端:
package netty;
import io.netty.bootstrap.ServerBootstrap;
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;
/**
* 时间服务器,当有客户端请求时,返回服务端当前时间
*/
public class TimeServer {
public void bind(int port){
//NioEventLoopGroup是一个线程组,它包含了一组NIO线程,
// 这里的两个线程组一个是用于服务端接受客户端的连接,
// 另一个用于SocketChannel的网络读写
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//netty用于启动NIO服务端的辅助启动类
ServerBootstrap b = new ServerBootstrap();
//设置线程组
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)//设置channel
.option(ChannelOption.SO_BACKLOG, 1024)//设置channel的TCP参数
.childHandler(new ChildChannelHandler());//绑定IO事件处理类
//绑定监听端口,调用同步阻塞方法等待绑定完成
ChannelFuture f = b.bind(port).sync();
//阻塞,等待服务端链路关闭后main函数才退出
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//优雅退出,释放跟shutdownGracefully相关联的所有资源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private class ChildChannelHandler extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel serverSocket) throws Exception {
//增加时间处理类
serverSocket.pipeline().addLast(new TimeServerHandler());
}
}
public static void main(String[] args) {
int port = 8080;
new TimeServer().bind(port);
}
}
服务端Handler:
package netty;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import java.util.Date;
/**
* 对网络事件进行读写操作
*/
public class TimeServerHandler extends ChannelHandlerAdapter {
/**
* 当异常发生时
* @param ctx
* @param cause
* @throws Exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//super.exceptionCaught(ctx, cause);
ctx.close();
}
/**
* 读取缓冲区里面的数据,处理并返回
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//super.channelRead(ctx, msg);
ByteBuf buf = (ByteBuf) msg;
//buf.readableBytes()返回缓冲区可读的字节数
byte [] bytes = new byte[buf.readableBytes()];
//读取缓冲区的数据至byte数组
buf.readBytes(bytes);
String data = new String(bytes,"UTF-8");
String currentTime = "query time order".equals(data)? new Date(System.currentTimeMillis()).toString(): "bad order";
//复制bytes数组的内容,构造一个缓冲区对象ByteBuf
ByteBuf rsp = Unpooled.copiedBuffer(currentTime.getBytes());
//异步发送消息给客户端
ctx.write(rsp);
}
/**
*
* @param ctx
* @throws Exception
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// super.channelReadComplete(ctx);
//ctx.write(rsp)发送消息时不是马上发送,而是将消息发送到发送缓冲区,等到读完成后
//再调用flush方法将发送缓冲区的消息全部写到SocketChannel中,发送给客户端
ctx.flush();
}
}
客户端:
package netty;
import io.netty.bootstrap.Bootstrap;
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.NioSocketChannel;
/**
* netty的客户端
*/
public class TimeClient {
public void connect(String host, int port){
//NioEventLoopGroup是一个线程组,它包含了一组NIO线程
EventLoopGroup group = new NioEventLoopGroup();
try {
//客户端辅助启动类
Bootstrap b = new Bootstrap();
//设置线程组
b.group(group)
.channel(NioSocketChannel.class)//设置Channel
.option(ChannelOption.TCP_NODELAY, true)//设置TCP的参数
.handler(new ChannelInitializer<SocketChannel>() {//匿名内部类设置handler
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new TimeClientHandler());
}
});
//异步连接客户端,同步阻塞直到连接成功
Chann