Chapter2 章节结构
1. Netty版本大致版本分为 netty3.x 和 netty4.x、netty5.x
2. 应用范围
1. 分布式进程通信
例如: hadoop、dubbo、akka等具有分布式功能的框架,底层RPC通信都是基于netty实现的,这些框架使用的版本通常都还在用netty3.x
2. 游戏服务器开发
最新的游戏服务器有部分公司可能已经开始采用netty4.x 或 netty5.x
3. Hello World案例
Server端
a. HelloServer
package com.john.netty.learn.ch02_03.server;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelSink;
import org.jboss.netty.channel.Channels;
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 HelloServer {
public HelloServer(int port) {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.setFactory(new NioServerSocketChannelFactory(boss, workers));
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline channelPipeline = Channels.pipeline();
channelPipeline.addLast("Decoder", new StringDecoder());
channelPipeline.addLast("HelloWorldHandler", new HelloChannelHandler());
channelPipeline.addLast("Encoder", new StringEncoder());
return channelPipeline;
}
});
serverBootstrap.bind(new InetSocketAddress(port));
}
private ExecutorService boss = Executors.newCachedThreadPool();
private ExecutorService workers = Executors.newCachedThreadPool();
public static void main(String[] args) {
new HelloServer(3000);
}
}
b. HelloChannelHandler
package com.john.netty.learn.ch02_03.server;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
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;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
public class HelloChannelHandler extends SimpleChannelHandler {
public HelloChannelHandler() {
}
/**
* 接收到消息
*/
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
// 没有过滤器
// ChannelBuffer channelBuffer = (ChannelBuffer) e.getMessage();
// System.out.println("接收到消息:" + new String(channelBuffer.array()));
// 回写数据
// ctx.getChannel().write(ChannelBuffers.wrappedBuffer(("Hi " +
// e.getMessage()).getBytes()));
// channelPipeline.addLast("Decoder", new StringDecoder());
System.out.println("接收到消息:" + e.getMessage());
// channelPipeline.addLast("Encoder", new StringEncoder());
ctx.getChannel().write("Hi " + e.getMessage());
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelConnected");
super.channelConnected(ctx, e);
}
/**
* 建立Channel成功,关闭通道时候,才会触发Disconnect
*/
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelDisconnected");
super.channelDisconnected(ctx, e);
}
/**
* Channel 关闭
*/
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelClosed");
super.channelClosed(ctx, e);
}
/**
* 捕获异常
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
e.getCause().printStackTrace();
super.exceptionCaught(ctx, e);
}
}
Client端
a. HelloClient
package com.john.netty.learn.ch02_03.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.ChannelFactory;
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.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import com.john.netty.learn.ch02_03.server.HelloChannelHandler;
public class HelloClient {
public HelloClient(String ip, int port) {
ClientBootstrap clientBootstrap = new ClientBootstrap();
clientBootstrap.setFactory(new NioClientSocketChannelFactory(boss, workers));
clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline channelPipeline = Channels.pipeline();
channelPipeline.addLast("Decoder", new StringDecoder());
channelPipeline.addLast("HiHandler", new HiChannelHandler());
channelPipeline.addLast("Encoder", new StringEncoder());
return channelPipeline;
}
});
ChannelFuture channelFuture = clientBootstrap.connect(new InetSocketAddress(ip, port));
Channel channel = channelFuture.getChannel();
System.out.println("client start");
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("Please input:");
channel.write(scanner.nextLine());
}
}
private ExecutorService boss = Executors.newSingleThreadExecutor();
private ExecutorService workers = Executors.newCachedThreadPool();
public static void main(String[] args) {
new HelloClient("127.0.0.1", 3000);
}
}
b. HiChannelHandler
package com.john.netty.learn.ch02_03.client;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
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;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
public class HiChannelHandler extends SimpleChannelHandler {
public HiChannelHandler() {
}
/**
* 接收到消息
*/
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
// 没有过滤器
// ChannelBuffer channelBuffer = (ChannelBuffer) e.getMessage();
// System.out.println("接收到消息:" + new String(channelBuffer.array()));
// 回写数据
// ctx.getChannel().write(ChannelBuffers.wrappedBuffer(("Hi " +
// e.getMessage()).getBytes()));
// channelPipeline.addLast("Decoder", new StringDecoder());
System.out.println("接收到消息:" + e.getMessage());
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelConnected");
super.channelConnected(ctx, e);
}
/**
* 建立Channel成功,关闭通道时候,才会触发Disconnect
*/
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelDisconnected");
super.channelDisconnected(ctx, e);
}
/**
* Channel 关闭
*/
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("channelClosed");
super.channelClosed(ctx, e);
}
/**
* 捕获异常
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
e.getCause().printStackTrace();
super.exceptionCaught(ctx, e);
}
}
Netty hello world 讲解说明:
1、netty服务端hello world案例
SimpleChannelHandler 处理消息接收和写
messageReceived接收消息
channelConnected新连接,通常用来检测IP是否是黑名单
hannelDisconnected链接关闭,可以再用户断线的时候清楚用户的缓存数据等
2、netty客户端hello world案例
channelDisconnected与channelClosed的区别?
channelDisconnected只有在连接建立后断开才会调用
channelClosed无论连接是否成功都会调用关闭资源