Netty编程(六)—— 实现一个回显Echo程序
之前五篇关于Netty的博客介绍了关于Netty的基础使用方法,这篇博客实现一个简单的Netty程序,他首先能够实现客户端和服务器的交互,客户可以任意输入内容(可以以某一命令结束客户端,例如quit),并将该内容发送给服务端,服务端接收到发来的消息后显示消息,并发送同样的消息给客户端,至此一次交互结束。这就是本篇博客要实现的Echo服务端和客户端的功能。
Echo服务端
因为对于Netty来说,服务端和客户端之间消息都是使用ByteBuf类型,所以对于服务端,首先要将传来的ByteBuf类型的消息转换成String类型,其次,需要一个处理read的handler,在这个handler需要得到转换的String字符串,输出,之后将该字符串转换成ByteBuf再转发给客户端。
public class EchoServer {
static final Logger log = LoggerFactory.getLogger(EchoServer.class);
public static void main(String[] args) {
NioEventLoopGroup boss = new NioEventLoopGroup(1);
NioEventLoopGroup worker = new NioEventLoopGroup(3);
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.group(boss, worker);
serverBootstrap.option(ChannelOption.SO_RCVBUF, 20);
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new StringDecoder());
socketChannel.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
ByteBuf buffer = socketChannel.alloc().buffer();
buffer.writeBytes(s.getBytes());
channelHandlerContext.writeAndFlush(buffer);
log.info("=========server received: " + s);
}
});
}
});
serverBootstrap.bind(8080).sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
Echo客户端
对于Echo客户端,首先需要一个处理读事件的handler,对于接收到的ByteBuf首先转成String类型的字符串然后输出,此外,在客户端程序的最后需要一个while循环,这个循环每次接收客户输入的内容,将其转换成ByteBuf类型后,使用与服务端建立好的channel将ByteBuf传递给服务端。
public class EchoClient {
static final Logger log = LoggerFactory.getLogger(EchoClient.class);
public static void main(String[] args) {
NioEventLoopGroup worker = new NioEventLoopGroup();
Scanner in = new Scanner(System.in);
try{
Bootstrap bootstrap = new Bootstrap();
bootstrap.channel(NioSocketChannel.class);
bootstrap.group(worker);
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
log.debug("connecting...");
socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf) msg;
int len = in.readableBytes();
byte[] arr = new byte[len];
in.getBytes(0, arr);
log.info("==================client received: " + new String(arr, "UTF-8"));
in.release();
}
});
}
});
ChannelFuture channelFuture = bootstrap.connect("localhost", 8080).sync();
while(in.hasNext())
{
String s = in.nextLine();
ByteBuf buffer = channelFuture.channel().alloc().buffer();
buffer.writeBytes(s.getBytes());
channelFuture.channel().writeAndFlush(buffer);
if(s.equals("quit"))
break;
}
channelFuture.channel().closeFuture().sync();
}catch (Exception e) {
e.printStackTrace();
}finally {
}
}
}
结果
服务端:
客户端: