到目前為止,我們一直在學習編寫伺服器處理數據但沒有做任何回應處理。 然而,伺服器通常應該回應請求。現在就來學習如何通過實現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.zaixian.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.zaixian.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
中發給伺服器,伺服器收到這消息後又發回給客戶端。
上一篇:
Netty實踐入門-編寫簡單伺服器
下一篇:
Netty實踐-時間伺服器