3、netty第二个例子,使用netty建立客户端,与服务端通讯
第一个例子中,建立了http的服务器端,可以直接使用curl命令,或者浏览器直接访问。
在第二个例子中,建立一个netty的客户端来主动发送请求,模拟浏览器发送请求。
这里先启动服务端,再启动客户端,启动客户端后,在 channelActive 方法中,主动向服务器端发送消息,服务器端channelRead0 方法中,接收到客户端的消息后,会再向客户端返回消息。客户端channelRead0方法中接收到消息再向客户端发送消息,依次往复。
同样的,按照顺序
client
1 import io.netty.bootstrap.Bootstrap; 2 import io.netty.channel.ChannelFuture; 3 import io.netty.channel.EventLoopGroup; 4 import io.netty.channel.nio.NioEventLoopGroup; 5 import io.netty.channel.socket.nio.NioServerSocketChannel; 6 import io.netty.channel.socket.nio.NioSocketChannel; 7 8 public class MyClient { 9 public static void main(String[] args) throws InterruptedException { 10 //客户端只需要一个 11 EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); 12 13 try{ 14 15 Bootstrap bootstrap = new Bootstrap(); 16 bootstrap.group(eventLoopGroup) 17 .channel(NioSocketChannel.class) 18 .handler(new MyClientInitlalizer()); 19 ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync(); 20 21 //channelFuture.channel().writeAndFlush("first msg");//发送数据,其实应该写到handler的active方法中 22 23 channelFuture.channel().closeFuture().sync(); 24 25 }finally { 26 eventLoopGroup.shutdownGracefully(); 27 } 28 29 } 30 }
Initlalizer
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.util.CharsetUtil; public class MyClientInitlalizer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline channelPipeline = ch.pipeline(); //添加解码器的handler channelPipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4)); channelPipeline.addLast(new LengthFieldPrepender(4)); //字符串的解码器 channelPipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); //字符串的编码器 channelPipeline.addLast( new StringEncoder(CharsetUtil.UTF_8)); //自定义的处理器 channelPipeline.addLast(new MyClientHandler()); } }
handler
1 import io.netty.channel.ChannelHandlerContext; 2 import io.netty.channel.SimpleChannelInboundHandler; 3 4 import java.time.LocalDateTime; 5 6 public class MyClientHandler extends SimpleChannelInboundHandler<String> { 7 @Override 8 protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { 9 System.out.println( ctx.channel().remoteAddress() + "," + msg); 10 System.out.println( "client output:" + msg); 11 12 ctx.writeAndFlush("from client" + LocalDateTime.now()); 13 } 14 15 @Override 16 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 17 cause.printStackTrace(); 18 ctx.close(); 19 //super.exceptionCaught(ctx, cause); 20 } 21 22 @Override 23 public void channelActive(ChannelHandlerContext ctx) throws Exception { 24 ctx.channel().writeAndFlush("来自客户端的问候!");//通道连接之后,发送数据 25 super.channelActive(ctx); 26 } 27 }
sever中的handle
server中的server代码和第一个例子类似,initlializer和client中的一致,就不贴代码了。
public class MyServerHandler extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println(ctx.channel().remoteAddress() + "," + msg); ctx.writeAndFlush("from serevber" + UUID.randomUUID());//消息返回 } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); // super.exceptionCaught(ctx, cause); } }