1 简单的客户端与服务端之间的通信
1.1 服务端
/**
* 服务端
*
* @author Tang 2018年5月13日
*/
public class TimeServer {
public void bind(Integer inetPort) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
bootstrap.childHandler(new ChilddChannelHandler());
ChannelFuture channelFuture = bootstrap.bind(inetPort).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private class ChilddChannelHandler extends
ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// TODO Auto-generated method stub
ch.pipeline().addLast(new TimeServerHandler());
}
}
public static void main(String[] args) {
new TimeServer().bind(8001);
}
}
消息处理类:
public class TimeServerHandler extends ChannelHandlerAdapter {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
ctx.close();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
System.out.println("接收到消息:" + body);
String currentTime = new Date().toString();
ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
ctx.write(resp);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
}
1.2 客户端
public class TimeClient {
public void connect(String host, Integer port) {
EventLoopGroup loopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(loopGroup);
bootstrap.channel(NioSocketChannel.class);
bootstrap.option(ChannelOption.TCP_NODELAY, true);
bootstrap.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new TimeClientHandler());
}
});
try {
ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
loopGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
new TimeClient().connect("127.0.0.1", 8001);
}
}
消息处理类:
/**
* 客户端
* @author Tang
* 2018年5月13日
*/
public class TimeClientHandler extends ChannelHandlerAdapter {
private static final String FIRST_MESSAGE = "Query Time";
private static final ByteBuf MSG = Unpooled
.buffer(FIRST_MESSAGE.getBytes().length);
static {
MSG.writeBytes(FIRST_MESSAGE.getBytes());
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(MSG);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
System.out.println("接收到消息" + body);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
ctx.close();
}
}
先启动服务端后再启动客户端,在控制台输入字符串后,客户端端将会收到消息。
2 单客户端多连接程序
对象池:
对象组:
初始化时创建多个对象,存储在数组中,调用的时候检测是否已断开连接
public class MultClient {
private Bootstrap bootstrap = new Bootstrap();
private List<Channel> channels = new ArrayList<Channel>();
private static final String HOST_NAME = "127.0.0.1";
private static final Integer PORT = 10101;
private static final InetSocketAddress SOCKET_ADDRESS = new InetSocketAddress(
HOST_NAME, PORT);
/**
* 引用计数
*/
private final AtomicInteger index = new AtomicInteger();
/**
* 初始化
* @param count
*/
public void init(int count) {
// worker
EventLoopGroup worker = new NioEventLoopGroup();
// 设置线程池
bootstrap.group(worker);
// 设置socket工厂
bootstrap.channel(NioSocketChannel.class);
// 设置管道
bootstrap.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ClientHandler());
}
});
for (int i = 1; i <= count; i++) {
ChannelFuture future = bootstrap.connect(SOCKET_ADDRESS);
channels.add(future.channel());
}
}
/**
* 获取会话
*
* @return
*/
public Channel nextChannel() {
return getFirstActiveChannel(0);
}
private Channel getFirstActiveChannel(Integer count) {
Channel channel = channels.get(Math.abs(index.getAndIncrement()
% channels.size()));
if (!channel.isActive()) {// 是否已连接
// 重连
reconnect(channel);
if (count >= channels.size()) {
throw new RuntimeException("no can use channel");
}
return getFirstActiveChannel(count + 1);
}
return channel;
}
/**
* 重新连接
*
* @param channel
*/
private void reconnect(Channel channel) {
synchronized (channel) {
if (channels.indexOf(channel) == -1) {
return;
}
Channel newChannel = bootstrap.connect(SOCKET_ADDRESS).channel();
channels.set(channels.indexOf(channel), newChannel);
}
}
}