如何让Netty管理任意客户端连接而非服务端连接?

最近在做一个项目,网址见:http://git.oschina.net/qiangzigege/MySQL-Binlog

要解决的一个问题就是:假如我想发起一个连接去连接mysql,成功后,如何让这个连接比较顺畅的纳入到netty的管理范围呢?

---不多说,上代码!

1)NettyQueue.java---存放连接队列

public class NettyQueue {

// poll: 若队列为空,返回null。

// remove:若队列为空,抛出NoSuchElementException异常。

// take:若队列为空,发生阻塞,等待有元素。

 

// put---无空间会等待

// add--- 满时,立即返回,会抛出异常

// offer---满时,立即返回,不抛异常

// private static final Logger logger =

// LoggerFactory.getLogger(MonitorQueue.class);

private static final Logger logger = LogManager.getLogger(NettyQueue.class);

public static BlockingQueue<Connection> objectQueue = new LinkedBlockingQueue<Connection>();

 

public static void addObject(Connection obj) {

objectQueue.offer(obj);

new Thread(new Runnable() {// 启动一个线程去触发...

@Override

public void run() {

// TODO Auto-generated method stub

MyProperties p = MyProperties.getInstance();

if (null != p) {// 连接本机的netty服务器

String ip = "127.0.0.1";

int port = p.getNetty_port();

if (null != ip && port >= 0) {

Socket socket = null;

try {

socket = new Socket();

System.out.println("ip: " + ip + " port:" + port);

socket.connect(new InetSocketAddress(ipport), 6 * 1000);// 还是给一个连接超时6秒

TimeUtils.sleepSeconds(6);// 睡眠6秒再退出,足够的时间给netty处理连接了

catch (Exception e) {

LoggerUtils.error(loggere.toString());

finally {

if (null != socket) {// 主动关闭连接

try {

socket.close();

catch (IOException e) {

}

}

// try...catch...finally结束

// if结束

}

}

}).start();

 

};

 

public static Connection getObject() {

return objectQueue.poll();

}

 

}


2)谁往里面放连接呢?

大体的代码是:

// 4)尝试创建连接conn

Connection conn = null;

int lastIndex = taskPath.lastIndexOf("/");

String target = taskPath.substring(lastIndex + 1);

String[] elements = target.split(":");

String ip = elements[0];

int port = Integer.valueOf(elements[1]);

try {

LoggerUtils.debug(logger"target machine:" + ip + ":" + port);

conn = ConnectionFactory.makeObject(ip, port, taskData, currentPath, binlogPositionPath, fn, fp);

catch (Exception e) {

LoggerUtils.debug(loggere.toString());

conn = null;

}

// conn = null;

if (null != conn) {// 创建成功

LoggerUtils.debug(logger"create socket succeed: " + conn.getSocketChannel());

NettyQueue.addObject(conn);

}


public static Connection makeObject(String ipint port, String data, String runningPath, String binlogPositionPath,

String initialFilenamelong initialPosition) {

Connection myConn = null;

 

if (null != ip && port >= 0) {

try {

// 在这里创建具体的对象,注意这里的用法

SocketAddress sAddress = new InetSocketAddress(ipport);

SocketChannel sChannel = SocketChannel.open(sAddress);

sChannel.configureBlocking(false);// 非阻塞

myConn = new Connection(sChannel,

ConnectionAttributes.parse(data).setIpPort(ipport).setRunningZKPath(runningPath)

.setBinlogPositionZKPath(binlogPositionPath)

.setClientId(Long.parseLong(ip.replaceAll(".""") + port))

.updateBinlogNameAndPosition(initialFilenameinitialPosition));

catch (Exception e) {

LoggerUtils.error(loggere.toString());

}

}

 

// 无论如何,都返回连接,失敗則返回null

return myConn;

}




3)谁负责取出来呢?

注意我们在第一部分是触发了一个连接本地127.0.0.1的一个连接,这个实际是连接本地的Netty服务器。

需要知道Netty如何启动的

EventLoopGroup workerGroup = new NioEventLoopGroup(worker);

try {

ServerBootstrap b = new ServerBootstrap();

b.group(bossGroupworkerGroup).channel(MyNioServerSocketChannel.class)

.option(ChannelOption.SO_BACKLOG, 2048).childHandler(new ChildChannelHandler());

// 绑定端口,同步等待成功

ChannelFuture f = b.bind(port).sync();

// 等待服务端监听端口关闭

LoggerUtils.info(logger"netty server start ok.");

f.channel().closeFuture().sync();

重点就在MyNioServerSocketChannel.class

public class MyNioServerSocketChannel extends NioServerSocketChannel {

private static final Logger logger = LogManager.getLogger(MyNioServerSocketChannel.class);

 

// 继承已经有的类,用于干预连接

@Override

protected int doReadMessages(List<Object> bufthrows Exception {

// logger.debug("\ndoReadMessages(...) enter....\n触发了新的连接...开始准备2阶段提取");

// logger.debug("buf :" + buf);

// LoggerUtils.debug(logger, new Exception().toString());

// 原始部分,直接关闭

try {

SocketChannel tempCh = javaChannel().accept();

tempCh.close();

catch (Exception e) {

 

}

 

// 移花接木

Connection connection = NettyQueue.getObject();

try {

if (connection != null) {

MyNioSocketChannel channel = new MyNioSocketChannel(thisconnection.getSocketChannel(),

connection.getAttributes());

buf.add(channel);

LoggerUtils.debug(logger"db conn is as follows: " + connection.getSocketChannel());

// logger.debug("buf :" + buf);

return 1;

}

catch (Throwable t) {

LoggerUtils.info(logger"Failed to create a new channel from an accepted socket." + t);

try {

connection.close();

catch (Throwable t2) {

LoggerUtils.info(logger"Failed to close a socket." + t2);

}

}

 

return 0;

 

}

}

所以,到这里应该就知道了,用了一种诱骗式的方法,

巧妙的绕过了Netty的平常只接收主动连接自己的服务端socket的限制

使得任意客户端连接都可以纳入netty的管理范围

同时对netty框架本身不构成任何入侵性。

你可能感兴趣的:(netty)