利用Java NIO 实现client端,支持自动重连

来源:互联网 发布:阿里云 p7待遇 股票 编辑:程序博客网 时间:2024/05/16 12:46

Java NIO 实现client端,相比较于Server端的实现,相对简单,如果要支持自动重新连接功能,就需要有线程同步的概念。以下代码实现了自动重新连接的功能,增加了一个具体的连接管理类Manager。

package com.sof.nio;import java.io.IOException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.sof.bas.Config;import com.sof.exe.Client;public class Manager implements Runnable {private static Logger logger = LoggerFactory.getLogger(Client.class);public boolean connstate = false;public String ip = Config.getInstance().getStringValue("ip");public int port = Config.getInstance().getIntValue("port");public void setestablished() {connstate = true;}public void setdisconnect() {connstate = false;}public boolean getconnstate() {return connstate;}public void run() {while (true) {Reactor reactor = null;try {reactor = new Reactor(ip, port, this);reactor.connecttoserver();logger.error("connect to server sucessful " + reactor.serveraddress.toString());} catch (IOException ex) {logger.error("connect to server unsucessful " + reactor.serveraddress.toString());continue;}while (getconnstate()) {try {synchronized (this) {this.wait();logger.debug("got a news about disconnection and reconnect to server" +  reactor.serveraddress.toString());}} catch (InterruptedException e) {logger.debug(e.getMessage());}}}}}


 

package com.sof.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.util.Set;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.sof.bas.Bytes2util;import com.sof.bas.Util2Bytes;public class Reactor implements Runnable {private static Logger logger = LoggerFactory.getLogger(Reactor.class);public Manager manager;final Selector selector;final SocketChannel socket;public SelectionKey sk;public InetSocketAddress serveraddress;static final int MESSAGE_LENGTH_HEAD = 4;private byte[] head = new byte[4];private int bodylen = -1;private int sequence = 0;public boolean done = true;public Reactor(String ip, int port, Manager manager) throws IOException {this.manager = manager;selector = Selector.open();socket = SocketChannel.open();socket.configureBlocking(true);serveraddress = new InetSocketAddress(ip, port);}public boolean connecttoserver() throws IOException {boolean result = false;socket.connect(serveraddress);result = true;new Thread(this).start();manager.setestablished();socket.configureBlocking(false);sk = socket.register(selector, 0);sk.interestOps(SelectionKey.OP_READ);selector.wakeup();return result;}public void run() {try {while (done) {logger.debug("selector is waitting  event....");selector.select();Set<SelectionKey> keys = selector.selectedKeys();if (keys.size() == 0) {logger.debug("nothing happened");continue;}for (SelectionKey key : keys) {if (key.isReadable()) {logger.debug("Readable event happened");readdata();} else if (key.isWritable()) {logger.debug("Writeable event happened");} else {logger.debug("others event happened");}}keys.clear();}logger.debug("thread exit");} catch (IOException ex) {logger.error(ex.getMessage());}}public void readdata() {try {read();} catch (IOException ex) {try {logger.debug("disconnection event happened");socket.close();synchronized (manager) {manager.setdisconnect();manager.notifyAll();done = false;}} catch (IOException e) {logger.error(e.getMessage());}sk.cancel();}}public void read() throws IOException {ByteBuffer input = ByteBuffer.allocate(1024 * 10000);socket.read(input);input.flip();sk.interestOps(SelectionKey.OP_READ);while (input.remaining() > 0) {if (bodylen < 0) {if (input.remaining() >= MESSAGE_LENGTH_HEAD) {input.get(head, 0, 4);bodylen = Util2Bytes.bytes2bigint(head);} else {break;}} else if (bodylen > 0) {if (input.remaining() >= bodylen) {byte[] body = new byte[bodylen];input.get(body, 0, bodylen);sequence++;byte[] headandbody = new byte[MESSAGE_LENGTH_HEAD + bodylen];System.arraycopy(head, 0, headandbody, 0, head.length);System.arraycopy(body, 0, headandbody, head.length,body.length);MsgBean message = new MsgBean(sequence, headandbody, socket);Process.getInstance().queue.put(message);bodylen = -1;} else {break;}} else if (bodylen == 0) {sequence++;byte[] headandbody = new byte[MESSAGE_LENGTH_HEAD + bodylen];System.arraycopy(head, 0, headandbody, 0, head.length);MsgBean message = new MsgBean(sequence, headandbody, socket);Process.getInstance().queue.put(message);bodylen = -1;}}}}