一、Netty概述
Netty 是由JBOSS提供的一个java开源框架,Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
Netty 是一个基于NIO的客户、服务器端编程框架,Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发,同时吸收了多种协议的实现经验,这些协议包括FTP,SMTP,HTTP,各种二进制,文本协议。
使用Netty可以实现一个Socket通讯,包括客户端和服务端,通过服务端进行监听,客户端发送信息,服务端可进行接收,并进行返回数据,完成一个完整的通讯。
二、基于netty channel的writeAndFlush 客户端发送信息实践,发送并接收反馈信息
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.util.concurrent.CountDownLatch;
public class ClientUtil {
private static final String SOCKET_SERVER_IP = "127.0.0.1";
private static final int SOCKET_SERVER_PORT = 8899;
public synchronized static String socketRequest(String requestStr) throws Exception{
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try {
CountDownLatch lathc = new CountDownLatch(1);
MyClientInitializer client = new MyClientInitializer(lathc);
//客户端启动器
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(client);
ChannelFuture channelFuture = bootstrap.connect(SOCKET_SERVER_IP, SOCKET_SERVER_PORT).sync();
if(channelFuture.isSuccess()){
Channel channel = channelFuture.channel();
channel.writeAndFlush(requestStr);
lathc.await();//开启等待会等待服务器返回结果之后再执行下面的代码
return client.getReturn_msg();
}
}catch(Exception e){
e.printStackTrace();
}finally{
eventLoopGroup.shutdownGracefully();
}
return null;
}
}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.time.LocalDateTime;
import java.util.concurrent.CountDownLatch;
public class MyClientHandler extends SimpleChannelInboundHandler<String> {
private String return_msg;
private CountDownLatch lathc;
public MyClientHandler(CountDownLatch lathc) {
this.lathc = lathc;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("client 获取返回信息: " + msg +",ip:"+ctx.channel().remoteAddress());
this.return_msg = msg;
lathc.countDown();
/* Thread.sleep(5000);
ctx.writeAndFlush("from client: " + LocalDateTime.now());*/
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
/**
* channel处于活动状态后的回调(链接建立好了过后)
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// ctx.channel().writeAndFlush("来与客户端!");
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
}
import java.util.concurrent.CountDownLatch;
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 MyClientInitializer extends ChannelInitializer<SocketChannel> {
private MyClientHandler myClientHandler;
private CountDownLatch lathc;
public MyClientInitializer(CountDownLatch lathc) {
this.lathc = lathc;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
myClientHandler = new MyClientHandler(lathc);
ChannelPipeline pipeline = ch.pipeline();
//编解码的处理
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
pipeline.addLast(new LengthFieldPrepender(4));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
//自己的处理器
pipeline.addLast(myClientHandler);
}
public String getReturn_msg() {
return myClientHandler.getReturn_msg();
}
}