在工作中遇到了使用netty编写转发数据的小程序,因为是第一次接触到netty所以 将写的心得记录如下:
客户端要连接到服务端,服务端需要有一个端口能够让客户端去绑定 方法bind,所以服务端会占用一个端口。
客户端去访问服务端的端口,需要有一个连接的方法,connect ,需要去访问ip和port。
1.netty客户端代码:
public class Client {
public static void main(String[] args) throws Exception {
String host = args[0];
int port = Integer.parseInt(args[1]);
EventLoopGroup workerGroup = new NioEventLoopGroup(); // (1)
try {
Bootstrap b = new Bootstrap(); // (2)
b.group(workerGroup); // (3)
b.channel(NioSocketChannel.class); // (4)
b.option(ChannelOption.SO_KEEPALIVE, true); // (5)
b.handler(new ChannelInitializer<SocketChannel>() { // (6)
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ClientHandler());
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync(); // (7)
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
}
}
客户端的开发步骤:
(1)、 初始化用于连接及I/O工作的"线程池";
(2)、 初始化Bootstrap实例, 此实例是netty客户端应用开发的入口,也是本篇介绍的重点, 下面我们会深入分析;
(3)、 通过Bootstrap的group方法,设置(1)中初始化的"线程池";
(4)、 指定通道channel的类型,由于是客户端,故而是NioSocketChannel;
(5)、 设置SocketChannel的选项(此处不详述,后面的系列会进行深入分析);
(6)、 设置SocketChannel的处理器
(7)、 连接指定的服务地址;
ClienHandler类
和server的Handler类差不多 可以参考ServerHandler
2.netty服务端代码:
创建的方法:
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup) // (3)
.channel(NioServerSocketChannel.class) // (4)
.handler(new LoggingHandler()) // (5)
.childHandler(new ChannelInitializer<SocketChannel>() { // (6)
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast( new ChildChannelHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128) // (7)
.childOption(ChannelOption.SO_KEEPALIVE, true); // (8)
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync(); // (9)
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
上面这段代码展示了服务端的一个基本步骤:
(1)、 初始化用于Acceptor的主"线程池"以及用于I/O工作的从"线程池"
(可以参考:https://my.oschina.net/u/438393/blog/845300)
(2)、 初始化ServerBootstrap实例, 此实例是netty服务端应用开发的入口
(3)、 通过ServerBootstrap的group方法,设置(1)中初始化的主从"线程池";
(4)、 指定通道channel的类型,由于是服务端,故而是NioServerSocketChannel;
(5)、 设置ServerSocketChannel的处理器(此处不详述,后面的系列会进行深入分析)
(6)、 设置子通道也就是SocketChannel的处理器, 其内部是实际业务开发的"主战场"(此处不详述,后面的系列会进行深入分析)
(7)、 配置ServerSocketChannel的选项
(8)、 配置子通道也就是SocketChannel的选项
(9)、 绑定并侦听某个端口
handler类:
@ChannelHandler.Sharable //让当前服务能够被多个channel 共享
public class ChildChannelHandler extends ChannelInboundHandlerAdapter { //继承adatper类
//channelread方法
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//原始数据 获取日志
try {
byte[] byteMessage = (byte[]) msg;
} catch (Exception e) {
e.printStackTrace();
log.error("操作出错:" + e);
}
}
服务端在初始化的时候回去new这个类 ,当服务连通后 client向服务器发送数据会在channelread方法里面去读取到。
当然还有其他关于channel 的方法 是针对于channel进行操作的时候使用的。