
jizcode.netty.client.RtClient Maven / Gradle / Ivy
package jizcode.netty.client;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import jizcode.base.util.JsonUtils;
import jizcode.netty.contract.BufferSize;
import jizcode.netty.contract.RtDataFromClient;
import jizcode.netty.contract.RtDataFromServer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class RtClient {
protected Log logger = LogFactory.getLog(this.getClass());
private static RtClient s_netttyclient;
public static RtClient getInstance() {
if (s_netttyclient == null) {
s_netttyclient = new RtClient();
}
return s_netttyclient;
}
private int port;
private String host;
private SocketChannel socketChannel;
private Function resolveCallback;
private Function connectCallback;
private Boolean isReconnecting;
private RtClient() {
isReconnecting = false;
}
public Function getResolveCallback() {
return this.resolveCallback;
}
/**
* connect to server
*
* @param host
* @param port
* @param connectCallback
* @param resolveCallback
*/
public void start(String host, int port, Function connectCallback,
Function resolveCallback) {
if (socketChannel == null) {
this.host = host;
this.port = port;
this.resolveCallback = resolveCallback;
this.connectCallback = connectCallback;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.channel(NioSocketChannel.class)
// 保持连接
.option(ChannelOption.SO_KEEPALIVE, true)
// 有数据立即发送
.option(ChannelOption.TCP_NODELAY, true)
// 绑定处理group
.group(eventLoopGroup).remoteAddress(host, port)
.handler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
// 初始化编码器,解码器,处理器
socketChannel.pipeline().addLast(new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS),
new RtIdleStateTrigger(), new LineBasedFrameDecoder(BufferSize.Default),
new StringDecoder(Charset.forName("utf-8")), new RtClientHandler());
}
});
// 进行连接
ChannelFuture future;
try {
future = bootstrap.connect(host, port).sync();
// 判断是否连接成功
if (future.isSuccess()) {
// 得到管道,便于通信
socketChannel = (SocketChannel) future.channel();
//logger.info("客户端开启成功...");
connectCallback.apply(true);
} else {
//logger.info("客户端开启失败...");
connectCallback.apply(false);
}
// 等待客户端链路关闭,就是由于这里会将线程阻塞,导致无法发送信息,所以我这里开了线程
future.channel().closeFuture().sync();
//logger.info("客户端退出...");
} catch (Exception e) {
connectCallback.apply(false);
e.printStackTrace();
} finally {
// 优雅地退出,释放相关资源
eventLoopGroup.shutdownGracefully();
}
}
});
thread.start();
}
}
/**
* 5秒后启动重连
*/
public synchronized void reconnect() {
if (isReconnecting == false) {
isReconnecting = true;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try {
//logger.info("客户端5秒后重连...");
Thread.sleep(5000);
//logger.info("客户端开始重连...");
Bootstrap bootstrap = new Bootstrap();
bootstrap.channel(NioSocketChannel.class)
// 保持连接
.option(ChannelOption.SO_KEEPALIVE, true)
// 有数据立即发送
.option(ChannelOption.TCP_NODELAY, true)
// 绑定处理group
.group(eventLoopGroup).remoteAddress(host, port)
.handler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
// 初始化编码器,解码器,处理器
socketChannel.pipeline().addLast(
new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS),
new RtIdleStateTrigger(), new LineBasedFrameDecoder(BufferSize.Default),
new StringDecoder(Charset.forName("utf-8")), new RtClientHandler());
}
});
// 进行连接
ChannelFuture future;
future = bootstrap.connect(host, port).sync();
// 判断是否连接成功
if (future.isSuccess()) {
// 得到管道,便于通信
socketChannel = (SocketChannel) future.channel();
connectCallback.apply(true);
isReconnecting = false;
//logger.info("客户端重连成功...");
} else {
connectCallback.apply(false);
//logger.info("客户端重连失败...");
isReconnecting = false;
RtClient.getInstance().reconnect();
}
// 等待客户端链路关闭,就是由于这里会将线程阻塞,导致无法发送信息,所以我这里开了线程
future.channel().closeFuture().sync();
//logger.info("客户端退出...");
} catch (Exception e) {
e.printStackTrace();
connectCallback.apply(false);
isReconnecting = false;
RtClient.getInstance().reconnect();
} finally {
// 优雅地退出,释放相关资源
eventLoopGroup.shutdownGracefully();
//logger.info("客户端重连失败,优雅地退出,释放相关资源...");
}
}
});
thread.start();
}
}
public synchronized void request(RtDataFromClient data) {
if (socketChannel != null) {
String msg = JsonUtils.tryToJson(data);
byte[] bytes = String.format("%s%s", msg, System.getProperty("line.separator")).getBytes();
ByteBuf byteBuf = Unpooled.buffer(bytes.length);
byteBuf.writeBytes(bytes);
socketChannel.writeAndFlush(byteBuf);
//logger.info("客户端发送消息:" + msg);
} else {
//logger.info("客户端发送消息: failure, channel is null");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy