use of io.transport.sdk.exception.TransportException in project transporter by wang4ever.
the class TransportChannel method connect.
public void connect(final boolean sync) {
try {
if (this.bootstrap == null)
this.configure();
// 获取当前负载均衡节点
HostAndPort hap = this.config.getRoutingBalancer().determineCurrentLookupNode();
// 配置完成,开始连接server, 通过调用sync同步方法阻塞直到连接成功
ChannelFuture cf = this.bootstrap.connect(hap.getHost(), hap.getPort());
// Reconnect listener.
cf.addListener((ChannelFuture f) -> {
if (!f.isSuccess()) {
f.channel().eventLoop().schedule(() -> {
config.getLogger().info("Reconnect to " + hap + " failed.");
// 更新连接失败(计数器,用于负载均衡计算)
config.getRoutingBalancer().onConnectFailed(hap);
// 重试连接
connect(sync);
}, config.getReconnectDelay(), TimeUnit.SECONDS);
} else {
this.config.getLogger().info("Connected to " + hap);
// 连接成功后重新登录
TransportClients.getInstance().login();
}
});
if (sync)
this.channel = cf.sync().channel();
else
this.channel = cf.channel();
} catch (Exception e) {
throw new TransportException("Connection failed.", e);
} finally {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
this.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}));
}
}
use of io.transport.sdk.exception.TransportException in project transporter by wang4ever.
the class TransportChannel method configure.
/**
* 建立连接并初始化Nio channel
*
* @return this
* @throws InterruptedException
*/
public TransportChannel configure() {
try {
if (this.bootstrap != null) {
this.config.getLogger().warn("Initialized bootloader.");
return this;
}
// 1.0 启动引导程序
this.bootstrap = new Bootstrap();
// 通过nio方式来接收连接和处理连接
this.workerGroup = new NioEventLoopGroup();
// 设置nio类型的channel
this.bootstrap.group(workerGroup);
this.bootstrap.channel(NioSocketChannel.class);
this.bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
// this.bootstrap.option(ChannelOption.SO_TIMEOUT,
// this.config.soTimeout());
this.bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.config.getConnecTimeout() * 1000);
// 有连接到达时会创建一个channel
this.bootstrap.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
// pipeline管理channel中的Handler,在channel队列中添加一个handler来处理业务
ChannelPipeline p = ch.pipeline();
if (config.isLoggingEnable() && config.getLevel().getValue() >= Level.DEBUG.getValue())
p.addLast(new LoggingHandler(LogLevel.valueOf(config.getLevel().name())));
p.addLast(new IdleStateHandler(config.getReadIdleSeconds(), config.getWriteIdleSeconds(), config.getAllIdleSeconds()));
p.addLast("decoder", new TransportMessageDecoder());
p.addLast("encoder", new TransportMessageEncoder());
p.addLast("receiveTextHandler", config.getHandler().newInstance());
}
});
// 线程在这里开始等待,除非有socket事件唤醒
// f.channel().closeFuture().sync();
// 2.0 反射强制设置默认JDK日志级别
// try {
// // Netty JdkLogger instance
// Field nettyJdkLogField =
// Bootstrap.class.getDeclaredField("logger");
// nettyJdkLogField.setAccessible(true);
// Object nettyJdkLogObj = nettyJdkLogField.get(null);
// // JdkLogger instance
// Field jdkLogField =
// nettyJdkLogObj.getClass().getDeclaredField("logger");
// jdkLogField.setAccessible(true);
// java.util.logging.Logger jdkLog = (java.util.logging.Logger)
// jdkLogField.get(nettyJdkLogObj);
// jdkLog.setLevel(Level.parse(this.config.getJdkLogLevel()));
// } catch (Exception e) {
// this.config.getLogger().error("设置Netty debugger日志级别失败. " +
// e.getMessage());
// }
} catch (Exception e) {
throw new TransportException("Connection channel configuration error.", e);
}
return this;
}
use of io.transport.sdk.exception.TransportException in project transporter by wang4ever.
the class TransportClient method unicast.
/**
* 单播发送消息(指定的点对点one-to-one)
*
* @param toDeviceId
* @param payload
* @return 通道对象(可用于控制同步发送方案: unicast(..).sync())
* @throws TransportException
*/
public Future<Message> unicast(String toDeviceId, String payload) throws TransportException {
if (ByteBufs.isEmpty(toDeviceId) || ByteBufs.isEmpty(payload))
throw new TransportException("'toDeviceId/payload' is not allowed to be empty.");
String fromDeviceId = this.config.getDeviceId();
TransportMessage msg = new TransportMessage(fromDeviceId, toDeviceId, payload);
return this.execute(msg, true);
}
use of io.transport.sdk.exception.TransportException in project transporter by wang4ever.
the class TransportClient method getChannel.
/**
* 获取channel
*
* @param activated
* 是否获取连接活跃的,否则等待
* @param loggedin
* 获取是否已认证的连接(TRUE:若未登录则会等待)
* @return
* @throws InterruptedException
*/
public synchronized TransportConnector getChannel(final boolean loggedin) {
if (this.connector == null)
throw new TransportInitializeException("Uninitialized client.");
if (loggedin) {
// 60*100=6000
int max = this.config.getLoginTimeout() * 100;
int c = 0;
while (c <= max) {
++c;
try {
this.wait(10L);
} catch (InterruptedException e) {
throw new TransportException(e);
}
if (!this.isAuthState()) {
// Unauthenticated
if (c == max) {
// 1.1 外抛未认证异常.
throw new TransportAuthenticationException("Authentication timeout.");
// 这种处理流程,会导致运行一段时间后线程会堵死???
//
// // 1.2 自动发起重认证流程
// this.client.channel().close(); // 关闭channel
// this.join(); // 重连、认证
}
} else
break;
}
}
return this.connector;
}
use of io.transport.sdk.exception.TransportException in project transporter by wang4ever.
the class TransportClients method registered.
/**
* 注册客户端连接认证(如:用于Web端ws连接认证)
*
* @param expiredSec
* 过期时间(s)
* @param deviceIdTokens
* 多个deviceId
* @return 通道对象(可用于控制同步发送方案: registered(..).sync())
* @throws TransportException
*/
public Future<Message> registered(int expiredSec, String... deviceIdTokens) throws TransportException {
if (!(deviceIdTokens != null && deviceIdTokens.length != 0))
throw new TransportException("The 'deviceIdTokens' is not allowed to be empty.");
if (expiredSec <= 0)
throw new TransportException("'expiredSec' is invalid.");
DeviceRegistMessage msg = new DeviceRegistMessage();
msg.setAppId(this.config.getAppId());
msg.setExpired(expiredSec);
msg.setClientDeviceIds(Arrays.asList(deviceIdTokens));
return this.execute(msg, true);
}
Aggregations