一、我与Netty
在去年就开始接触netty了,我们项目的服务端通信就是用netty,在这上面做了一层封装后,开发真的很方便。刚开始没有仔细去看框架的源代码,只是在上面写写逻辑而已。经过有些需求后,发现不得不去了解一下底层是如何实现的,下面我把自己的学习和实践,在这里与大家作一个分享。
二、Netty与HelloWorld
先从HelloWorld开始!Netty实现通讯比NIO相对简单,它对轮询线程和四种不同键的操作已经封装好了,相比我前面博客写的NIO例子,要少写很多代码,这也是Netty流行的一个原因吧。
Server:
package com.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import com.netty.handler.ServerChannelInitializer;
/**
*
* @author Jack Lei
* @email 895896736@qq.com
* @date 2016年3月5日 下午3:04:51
*/
public class Server {
public Server(int port) {
/* boss线程组:处理客户端连接* */
EventLoopGroup boss = new NioEventLoopGroup();
/* work线程组:处理IO读写* */
EventLoopGroup wrok = new NioEventLoopGroup();
/* 服务器启动辅助类:* */
ServerBootstrap boot = new ServerBootstrap();
/* 配置两个线程组与ServerSokcetChannel,设置channel的参数,channle处理类* */
boot.group(boss, wrok)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.childHandler(new ServerChannelInitializer());
try {
/* 绑定端口后调用同步阻塞方法sync,等待绑定完成,返回回调实例* */
ChannelFuture future = boot.bind(port).sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 释放资源
boss.shutdownGracefully();
wrok.shutdownGracefully();
}
}
public static void main(String[] args) {
new Server(8888);
}
}
package com.netty.handler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
/**
*
* @author Jack Lei
* @email 895896736@qq.com
* @date 2016年3月5日 下午3:28:37
*/
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ServerHandler());
}
}
package com.netty.handler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/**
*
* @author Jack Lei
* @email 895896736@qq.com
* @date 2016年3月5日 下午3:05:21
*/
public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
int size = buf.readableBytes();
byte[] body = new byte[size];
buf.readBytes(body);
System.out.println("Recive Message From Client : size = " + size + " body =" + new String(body));
ByteBuf resp = Unpooled.buffer();
String respStr = "WelCome To Server.";
resp.writeBytes(respStr.getBytes("UTF-8"));
ctx.writeAndFlush(resp);
}
}
package com.netty;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
*
* @author Jack Lei
* @email 895896736@qq.com
* @date 2016年3月5日 下午3:42:02
*/
public class Client {
public Client(String host, int port) {
EventLoopGroup work = new NioEventLoopGroup();
Bootstrap boot = new Bootstrap();
boot.group(work)
.channel(NioSocketChannel.class)
.handler(new ClientChannelInitializer());
try {
ChannelFuture futrue = boot.connect("127.0.0.1", port);
futrue.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
work.shutdownGracefully();
}
}
class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ClientChannelHandler());
}
}
class ClientChannelHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ByteBuf buf = Unpooled.buffer();
String body = "Hello Server.";
buf.writeBytes(body.getBytes("UTF-8"));
ctx.writeAndFlush(buf);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
int size = buf.readableBytes();
byte[] body = new byte[size];
buf.readBytes(body);
System.out.println("Recive message from server : " + new String(body,
"UTF-8"));
}
}
public static void main(String[] args) {
new Client("1127.0.0.1", 8888);
}
}
三、Netty与你
HelloWorld写完了,实现了服务器和客户端的通信,或许你心中还有很多个为什么,也在纠结某一行代码,这个类是做什么的,为什么代码要这样写呢?(如果基础好,就另当别论了,哈哈)。先know how,再know why,在后面具体的需求中,遇到问题再研究这些细节,从这些问题中学习Netty.