-
上一篇: 【笔记】RPC 架构 - 1 - (OIO、NIO对比)、netty服务端(声明周期、StringDecoder、StringEncoder、名词说明,如:boss、worder)
-
源码下载【包含视频资料】 - Github
netty
上一篇,介绍了netty服务端简单的创建
下面介绍 客户端简单的创建
# netty 客户端(续上一篇)
创建 Client 类
package cn.edut.client;
import java.net.InetSocketAddress;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
public class Client {
public static void main(String[] args) {
// 服务类
ClientBootstrap bootstrap = new ClientBootstrap();
// 线程池
ExecutorService bossExecutor = Executors.newCachedThreadPool();
ExecutorService workerExecutor = Executors.newCachedThreadPool();
// socket工厂
bootstrap.setFactory(new NioClientSocketChannelFactory(bossExecutor, workerExecutor));
// 管道工厂
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("hiHandler", new HiHandler());
return pipeline;
}
});
// 连接服务端
ChannelFuture connect = bootstrap.connect(new InetSocketAddress("127.0.0.1",10101));
Channel channel = connect.getChannel();
System.out.println("client start");
Scanner scanner = new Scanner(System.in) ;
while(true) {
System.out.println("请输入:");
channel.write(scanner.nextLine()) ;
}
}
}
完成 HiHandler (跟 HelloHandler 差不多,需要继承 SimpleChannelHandler)
package cn.edut.client;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
public class HiHandler extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("messageReceived");
System.out.println("MessageEvent:" + e);
// 获取服务端信息
String message = (String) e.getMessage();
System.out.println("message:" + message);
super.messageReceived(ctx, e);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
System.out.println("exceptionCaught");
super.exceptionCaught(ctx, e);
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelConnected");
super.channelConnected(ctx, e);
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelDisconnected");
super.channelDisconnected(ctx, e);
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelClosed");
super.channelClosed(ctx, e);
}
}
## 直接启动
不启动服务端,直接启动客户单
我们看下打印
因为没有创立连接 ,因此 channelDisconnected
没有被打印
而是打印了 channelClosed
因为出现了异常,因此 exceptionCaught
被打印
最后抛出异常 java.net.ConnectException: Connection refused: no further information: /127.0.0.1:10101
。
## 启动服务器,再启动
客户端连接
客户端发数据
客户端断开
# 源码分析
netty 在 nio 基础上, 做了两件事
- 开启多个 selector ,对 selector 进行分区管理(workers)
- 在 大门(端口监听)那里,单独创建 selector 管理(boss)
(如下图)