Netty是一款用于快速开发高性能的网络应用程序的Java框架,是一个异步事件驱动的网络应用框架。
导入依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.5.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
创建一个Netty程序
1. ClientHandle
public class ClientHandle extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext channelHandlerContext) throws Exception {
System.out.println("客户端已激活");
channelHandlerContext.writeAndFlush("Hello world");
}
@Override
public void channelInactive(ChannelHandlerContext channelHandlerContext) throws Exception {
System.out.println("客户端已关闭");
}
@Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
System.out.println("发送消息");
}
@Override
public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable throwable) throws Exception {
throwable.printStackTrace();
channelHandlerContext.channel().close();
}
}
2. Client
public class Client {
private int port;
private String ip;
public Client(int port,String ip){
this.port=port;
this.ip=ip;
}
public void start(){
EventLoopGroup eventExecutors=new NioEventLoopGroup();
Bootstrap bootstrap=new Bootstrap();
bootstrap.group(eventExecutors)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline channelPipeline=socketChannel.pipeline();
channelPipeline.addLast("decoder", new StringDecoder());
channelPipeline.addLast("encoder", new StringEncoder());
channelPipeline.addLast(new ClientHandle());
}
});
try {
ChannelFuture channelFuture=bootstrap.connect("127.0.0.1",9999).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3. ServerHandle
public class ServerHandle extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext channelHandlerContext) throws Exception {
System.out.println("服务端已激活");
}
@Override
public void channelInactive(ChannelHandlerContext channelHandlerContext) throws Exception {
System.out.println("服务端已关闭");
}
@Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
System.out.println("接收到从客户端"+channelHandlerContext.channel().remoteAddress()+"的消息:"+o.toString());
}
@Override
public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable throwable) throws Exception {
throwable.printStackTrace();
channelHandlerContext.channel().close();
}
}
4. Server
public class Server {
private int port;
//private String ip;
public Server(int port){
// this.ip=ip;
this.port=port;
}
public void start(){
EventLoopGroup listerloopGroup=new NioEventLoopGroup();
EventLoopGroup workLoopGroup=new NioEventLoopGroup();
ServerBootstrap serverBootstrap=new ServerBootstrap();
serverBootstrap.group(listerloopGroup,workLoopGroup)
.channel(NioServerSocketChannel.class)
.localAddress(port)
.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline channelPipeline=socketChannel.pipeline();
channelPipeline.addLast("decoder", new StringDecoder());
channelPipeline.addLast("encoder", new StringEncoder());
channelPipeline.addLast(new ServerHandle());
}
});
try {
ChannelFuture channelFuture=serverBootstrap.bind(port).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上述程序表示了客户端连到服务端时,客户端向服务端发送一条Hello world
的信息。
组件初解
- EventLoopGroup、EventLoop、Channel
-
EventLoopGroup为Netty的事件循环组,里面包含了多个EventLoop,服务端一般具有两个事件循环组,一个用于监听新的连接,另外一个来处理已连接的客户端,当然也可以使用一个,那么这两者都在一个事件循环组里进行。
-
每个EventLoop代表着一个线程,用来处理其绑定的Channel的所有事件,且每个EventLoop可以被绑定多个Channel。
- ChannelHandlr、ChannelPipline、ChannelHandleContext
- 每个Channel都有一条ChannelPipline,每个ChannelPipline里面包括多个ChannelHandle(至少一个)
- ChannelHandle用来处理流经Channel的数据,通过ChannelHandleContext将每个ChannelHandle处理的结果连接起来
- ChannelInboundHandlerAdapter、ChannelOutboundHandlerAdapter
- ChannelInboundHandlerAdapter对应着入站事件(读事件、注册事件等),相反ChannelOutboundHandlerAdapter对应着出站事件(写事件等)
- 这两者是相对的概念,对服务器来言,服务端写入客户端称之为出站,而对于客户端来言,客户端写入服务器称为出站
- ServerBootstrap、Bootstrap
- ServerBootstrap对应服务端的启动类,而Bootstrap对应着客户端的启动类
- 大部分的配置都在启动类上进行的,包括指明传输方式、配置ChannelHandle等
- childHandler方法、Handle方法
- childHandler方法为已被接受的子Channel处理,代表着一个绑定到远程节点的套接字,也就是为每个客户端设置ChannelHandle,用来处理每个客户端除了连接的操作
- Handle方法添加的ChannelHandle由ServerChannel处理,代表着为服务端创建新的子Channel并处理,其实就是处理新的客户端连接
注意事项
- 传输时必须对消息进行利用解码器与编码器进行编码和解码,否则传输的消息接收不到
- 服务端与客户端指定的传输方式必须一致,即服务端指定传输方式为NIO,则客户端也必须使用NIO