简单的介绍一些服务端代码的编写顺序。
1.得到 ServerBootstrap的对象,用来监听客户端
ServerBootstrap serverBootstrap = new ServerBootstrap();
2.创建两个线程池
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
boss用来对端口的监听,worker对数据进行处理
3.设置工厂
serverBootstrap.group(boss, worker);
serverBootstrap.channel(NioServerSocketChannel.class);
4.设置,可以理解为netty3中的管道
serverBootstrap.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
/**
* 将“上传下载”数据装饰成String类型
*/
channel.pipeline().addLast(new StringDecoder());
channel.pipeline().addLast(new StringEncoder());
// 要处理的Handler
channel.pipeline().addLast(new ServerHandler2());
}
});
5.设置TCP参数
serverBootstrap.option(ChannelOption.SO_BACKLOG, 2048);// serverSocketchannel的设置,链接缓冲池的大小
serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);// socketchannel的设置,维持链接的活跃,清除死链接
serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);// socketchannel的设置,关闭延迟发送
6.绑定端口
ChannelFuture future = serverBootstrap.bind(new InetSocketAddress(
9090));
7.(等待)关闭客户端
Channel channel = future.channel();
channel.closeFuture().sync();
完整代码如下:
服务端:
package com.netty5.server;
import java.net.InetSocketAddress;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
/**
* @author Chalmers 2016年2月20日 下午7:52:49
*/
public class NettyServer2 {
public static void main(String[] args) {
// 得到ServerBootstrap对象
ServerBootstrap serverBootstrap = new ServerBootstrap();
// 创建线程池
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
try {
// 类似于Netty3中的工厂
serverBootstrap.group(boss, worker);
serverBootstrap.channel(NioServerSocketChannel.class);
// 类似于Netty3中的管道
serverBootstrap.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
/**
* 将“上传下载”数据装饰成String类型
*/
channel.pipeline().addLast(new StringDecoder());
channel.pipeline().addLast(new StringEncoder());
// 要处理的Handler
channel.pipeline().addLast(new ServerHandler2());
}
});
// 设置参数,TCP参数
serverBootstrap.option(ChannelOption.SO_BACKLOG, 2048);// serverSocketchannel的设置,链接缓冲池的大小
serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);// socketchannel的设置,维持链接的活跃,清除死链接
serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);// socketchannel的设置,关闭延迟发送
// 绑定端口,并且返回ChannelFuture对象
ChannelFuture future = serverBootstrap.bind(new InetSocketAddress(
9090));
System.out.println("启动服务器...");
// 等待客户端的关闭
Channel channel = future.channel();
// 要记得是closeFuture(),作用是等待服务端的关闭
channel.closeFuture().sync();
// 该条语句不会输出,原因:上面没有关闭...
// System.out.println("客户端已经关闭...");
} catch (Exception e) {
e.printStackTrace();
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
}
class ServerHandler2 extends SimpleChannelInboundHandler<String> {
@Override
protected void messageReceived(ChannelHandlerContext arg0, String arg1)
throws Exception {
// 输出接收到的数据
System.out.println(arg1);
// 向客户端发送数据
arg0.channel().writeAndFlush("hi");
}
/**
*
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
System.out.println("channelActive");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
System.out.println("channelInactive");
}
}
客户端:
package com.netty.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
/**
* @author Chalmers 2016年2月20日 下午8:31:25
*/
public class Client {
public static void main(String[] args) {
Bootstrap bootstrap = new Bootstrap();
EventLoopGroup worker = new NioEventLoopGroup();
bootstrap.channel(NioSocketChannel.class);
bootstrap.group(worker);
bootstrap.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(new StringEncoder());
channel.pipeline().addLast(new StringDecoder());
channel.pipeline().addLast(new ClientHandler());
}
});
ChannelFuture future = bootstrap.connect("127.0.0.1", 9090);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.print("输入: ");
try {
String line = br.readLine();
future.channel().writeAndFlush(line);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ClientHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void messageReceived(ChannelHandlerContext arg0, String arg1)
throws Exception {
System.out.println("收到服务端发送的消息..." + arg1);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
}
}
因为netty5与netty3的差别挺大,所以注意区分开。
http://moonmonster.iteye.com/blog/2278672
当然,因为本人水平有限,所以更详细的解释可见
netty权威指南作者的博客