com.gateway.connector.tcp.client.TcpClient Maven / Gradle / Ivy
package com.gateway.connector.tcp.client;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gateway.connector.proto.Proto;
import com.gateway.connector.tcp.client.ProxyInfo.ProxyType;
import com.gateway.connector.tcp.codec.TcpProtoDecoder;
import com.gateway.connector.tcp.codec.TcpProtoEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.proxy.HttpProxyHandler;
import io.netty.handler.proxy.ProxyHandler;
import io.netty.handler.proxy.Socks4ProxyHandler;
import io.netty.handler.proxy.Socks5ProxyHandler;
import io.netty.handler.ssl.SslHandler;
/**
* 支持 1.心跳 3s 发送一次心跳 2.连接登录 3.断开连接 4.同步请求/响应 5.订阅/退订 6.连接状态
*
* @author deshuai.kong
*
*/
public class TcpClient {
private final Logger logger = LoggerFactory.getLogger(TcpClient.class);
private String host = "127.0.0.1";
private int port = 2000;
private int protocal;
private boolean isGzip = false;
private ProxyInfo proxyInfo;
private ReadProtoProcess rsprpp = new ReadProtoProcess();
private ReadProtoProcess notifyrpp = new ReadProtoProcess();
public ProxyInfo getProxyInfo() {
return proxyInfo;
}
public void setProxyInfo(ProxyInfo proxyInfo) {
this.proxyInfo = proxyInfo;
}
public boolean isGzip() {
return isGzip;
}
public void setGzip(boolean isGzip) {
this.isGzip = isGzip;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
private Bootstrap bootstrap;
private EventLoopGroup group;
private Channel channel = null;
private IClientListener listener;
private boolean isStop = false;
public boolean isStop() {
return isStop;
}
public TcpClient(IClientListener listener) {
this.listener = listener;
rsprpp.listener=listener;
notifyrpp.listener=listener;
}
/**
* Init Bootstrap
*/
private final void getBootstrap() {
isStop = false;
if (group == null) {
group = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(group);
bootstrap.channel(NioSocketChannel.class);
bootstrap.handler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
proxyHandler(pipeline);
if (protocal == 2) {
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManager[] tm = { new cTrustManager() };
sslContext.init(null, tm, null);
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setUseClientMode(true);
sslEngine.setNeedClientAuth(false);
pipeline.addLast("ssl", new SslHandler(sslEngine));
}
pipeline.addLast(new LoggingHandler());
pipeline.addLast("decoder", new TcpProtoDecoder(isGzip));
pipeline.addLast("encoder", new TcpProtoEncoder(isGzip));
pipeline.addLast("handler", new TcpClientHandler(rsprpp,notifyrpp,listener));
}
private void proxyHandler(ChannelPipeline pipeline) {
if (proxyInfo != null && proxyInfo.getProxyType() != null) {
SocketAddress proxyAddress = new InetSocketAddress(proxyInfo.getProxyHost(),
proxyInfo.getProxyPort());
ProxyHandler proxyHandler = null;
if (ProxyType.http.equals(proxyInfo.getProxyType())) {
if (proxyInfo.getProxyUser()!=null&&!proxyInfo.getProxyUser().isEmpty()
&& proxyInfo.getProxyPassword()!=null&&!proxyInfo.getProxyPassword().isEmpty()) {
proxyHandler = new HttpProxyHandler(proxyAddress, proxyInfo.getProxyUser(),
proxyInfo.getProxyPassword());
} else {
proxyHandler = new HttpProxyHandler(proxyAddress);
}
} else if (ProxyType.socks5.equals(proxyInfo.getProxyType())) {
if (proxyInfo.getProxyUser()!=null&&!proxyInfo.getProxyUser().isEmpty()
&& proxyInfo.getProxyPassword()!=null&&!proxyInfo.getProxyPassword().isEmpty()) {
proxyHandler = new Socks5ProxyHandler(proxyAddress, proxyInfo.getProxyUser(),
proxyInfo.getProxyPassword());
} else {
proxyHandler = new Socks5ProxyHandler(proxyAddress);
}
} else if (ProxyType.socks4.equals(proxyInfo.getProxyType())) {
if (proxyInfo.getProxyUser()!=null&&!proxyInfo.getProxyUser().isEmpty()) {
proxyHandler = new Socks4ProxyHandler(proxyAddress, proxyInfo.getProxyUser());
} else {
proxyHandler = new Socks4ProxyHandler(proxyAddress);
}
}
pipeline.addFirst(proxyHandler);
}
}
});
bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000);
bootstrap.option(ChannelOption.TCP_NODELAY, true);
}
}
public synchronized boolean connect() {
if (channel != null && channel.isActive()) {
return true;
}
try {
channel = bootstrap.connect(host, port).sync().channel();
} catch (Exception e) {
logger.info("Connect Server (host[" + host + "]:port[" + port + "]) Failure." + e);
return false;
}
return true;
}
public synchronized void disConnect() {
isStop = true;
if (channel != null && channel.isActive()) {
channel.close();
}
if (group != null) {
group.shutdownGracefully();
group = null;
}
if(this.rsprpp!=null) {
rsprpp.dispose();
}
if(this.notifyrpp!=null) {
notifyrpp.dispose();
}
}
public void sendMessage(Proto msg) throws Exception {
if (channel != null) {
channel.writeAndFlush(msg);
}
}
public boolean connect(String host, int port, int protocal) {
this.host = host;
this.port = port;
this.protocal = protocal;
getBootstrap();
return connect();
}
private class cTrustManager implements TrustManager, X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
}