到目前为止,我们一直在学习编写服务器处理数据但没有做任何响应处理。 然而,服务器通常应该响应请求。现在就来学习如何通过实现ECHO协议向客户端写入响应消息,将接收到任何数据发送回客户端。
与上一个示例中实现的”丢弃”(discard )服务器的唯一区别是,它将接收到的数据发送回来,而不是将接收的数据打印到控制台。因此,再次修改channelRead()方法就足够了:
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ctx.write(msg); // (1)
ctx.flush(); // (2)
}
ChannelHandlerContext对象提供了各种操作,使您能够触发各种I/O事件和操作。 这里,我们调用write(Object)来逐字写入接收到的消息。请注意,不像我们在DISCARD示例中,这里没有释放收到的消息。这是因为Netty在写出来的时候就自动释放它了。
ctx.write(Object)并不会将消息写入线路。 它在内部缓冲,然后可通过ctx.flush()刷新到线。 或者,为了简洁,您可以调用ctx.writeAndFlush(msg)。
如果再次运行 telnet localhost 8080 命令,将看到服务器发回您已发送给它的内容。
EchoServerHandler.java 文件的代码如下所示 -
package com.yiibai.netty.echo;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
/**
* Handler implementation for the echo server.
*/
@Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf in = (ByteBuf) msg;
System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8));
ctx.write(in);
//ctx.write(msg);
ctx.flush();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
}
EchoClientHandler.java 文件的代码如下所示 -
package com.yiibai.netty.echo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
/**
* Handler implementation for the echo client. It initiates the ping-pong
* traffic between the echo client and server by sending the first message to
* the server.
*/
public class EchoClientHandler extends ChannelInboundHandlerAdapter {
private final ByteBuf firstMessage;
/**
* Creates a client-side handler.
*/
public EchoClientHandler() {
firstMessage = Unpooled.buffer(EchoClient.SIZE);
for (int i = 0; i < firstMessage.capacity(); i ++) {
firstMessage.writeByte((byte) i);
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("Connected");
ctx.writeAndFlush(Unpooled.copiedBuffer("This msg from clien!", CharsetUtil.UTF_8));
//ctx.writeAndFlush(firstMessage);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf in = (ByteBuf) msg;
System.out.println("Msg Form Server: " + in.toString(CharsetUtil.UTF_8));
//ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
}
运行测试:
首页先运行 EchoServer.java, 然后再运行 EchoClient.java ,得到如下结果 -
EchoServer.java输出结果如下:
三月 01, 2017 3:10:56 上午 io.netty.handler.logging.LoggingHandler channelRegistered
信息: [id: 0xe42c7db3] REGISTERED
三月 01, 2017 3:10:56 上午 io.netty.handler.logging.LoggingHandler bind
信息: [id: 0xe42c7db3] BIND: 0.0.0.0/0.0.0.0:8007
三月 01, 2017 3:10:56 上午 io.netty.handler.logging.LoggingHandler channelActive
信息: [id: 0xe42c7db3, L:/0:0:0:0:0:0:0:0:8007] ACTIVE
三月 01, 2017 3:11:07 上午 io.netty.handler.logging.LoggingHandler channelRead
信息: [id: 0xe42c7db3, L:/0:0:0:0:0:0:0:0:8007] RECEIVED: [id: 0xf1e9f9a2, L:/127.0.0.1:8007 - R:/127.0.0.1:59492]
Server received: This msg from clien!
EchoClient.java输出结果如下:
Connected
Msg Form Server: This msg from clien!
消息“This msg from clien!”先是从 EchoClient.java 中发给服务器,服务器收到这消息后又发回给客户端。