Netty是基于事件驱动的、异步的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。是一种NIO框架,下面从最简单的Hello World示例开始,演示服务端和客户端交互进行Netty交互。
1.首先,创建服务端
public class DiscardServer {
private int port;
public DiscardServer(int port) {
super();
this.port = port;
}
public void run() {
//配置Server
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()
));
//设置pipeFactory
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline(new DiscardServerHandler());
return pipeline;
}
});
//绑定server端端口
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) {
new DiscardServer(8080).run();
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
2、创建服务端事件处理的站点Handler,里面包含回调方法用于处理与客户端交互时的操作。
class DiscardServerHandler extends SimpleChannelHandler {
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
System.out.println("--------服务端-------");
String str = "Hello world, I'm server";
ChannelBuffer buffer = ChannelBuffers.buffer(str.length());
buffer.writeBytes(str.getBytes());
e.getChannel().write(buffer);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
System.out.println("服务端接收到消息:" + buffer.toString(Charset.defaultCharset()));
}
}
3、创建客户端
public class TimeClient {
private String host;
private int port;
public TimeClient(String host, int port) {
super();
this.host = host;
this.port = port;
}
public void run() {
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()
)
);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
//ChannelPipeline 管道、传输途径
@Override
public ChannelPipeline getPipeline() throws Exception {
// ChannelPipeline pipeline = Channels.pipeline();
// pipeline.addLast("encode", new StringEncoder());
// pipeline.addLast("decode", new StringDecoder());
// pipeline.addLast("handler", new TimeClientHandler());
return Channels.pipeline(new TimeClientHandler());
}
});
// bootstrap.setOption("tcpNoDelay", true);
// bootstrap.setOption("keepAlive", true);
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection is closed or the connection attempt fails.
future.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) {
new TimeClient("127.0.0.1", 8080).run();
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
4、创建客户端的Handler
class TimeClientHandler extends SimpleChannelHandler {
//这个属于事件相关的处理
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
System.out.println("-----------客户端---------------");
String msg = "Hello world, I'm client";
ChannelBuffer buffer = ChannelBuffers.buffer(msg.length());
buffer.writeBytes(msg.getBytes());
e.getChannel().write(buffer);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
ChannelBuffer acceptBuff = (ChannelBuffer) e.getMessage();
String info = acceptBuff.toString(Charset.defaultCharset());
System.out.println("客户端接收到消息:" + info);
e.getChannel().close();
}
}
5、先启动server端,再启动client端。可以分别在服务端和客户端的控制台看到如下消息:
server console:
--------服务端-------
服务端接收到消息:Hello world, I'm client
client console:
-----------客户端---------------
客户端接收到消息:Hello world, I'm server
6、
注意在handler中,传递字符串必须以ChannelBuffer为载体,不能直接用String传递。
当客户端和服务端连接上后,先回调的是channelConnected方法;之后才是messageReceived方法。
至此,就完成了Netty客户端与服务端的简单交互!