Java nio 客户端连接Server

在做通信系统的开发过程中,经常需要使用Socket通信。java新的io机制给我提供了一个很好的异步socket通信方式,这段时间用java写了一个客户端用来连接server。发现运行效率还比较让人满意。下面是我实现的部分功能。

连接服务器的socket,多线程启动。如果连接失败就重连。

Java代码   收藏代码
  1. public class CommonSocket extends Thread {  
  2.     private SocketChannel socketChannel;  
  3.     private boolean stop = false;  
  4.     private int port = 0;  
  5.     private String ip = "";  
  6.     private Selector selector = null;  
  7.     private SocketAddress socketAddress = null;  
  8.     private Logger logger = Logger.getLogger(CommonSocket.class);  
  9.   
  10.     public CommonSocket() {  
  11.         this.ip = SocketInfoUtils.TCP_IP;  
  12.         this.port = SocketInfoUtils.TCP_PORT;  
  13.     }  
  14.   
  15.     public void run() {  
  16.         while (!stop) {  
  17.             socketConnet();  
  18.             try {  
  19.                 sleep(5000);  
  20.             } catch (InterruptedException e) {  
  21.                 logger.error("SocketConnect run error: InterruptedException");  
  22.             }  
  23.         }  
  24.     }  
  25.   
  26.     public void socketBuilder() {  
  27.         try {  
  28.             selector = Selector.open();  
  29.         } catch (IOException e) {  
  30.             e.printStackTrace();  
  31.             logger.error("Open to selector failed: IOException");  
  32.         }  
  33.     }  
  34.   
  35.     private void openSocketChannel() {  
  36.         try {  
  37.             socketAddress = new InetSocketAddress(ip, port);  
  38.             socketChannel = SocketChannel.open();  
  39.             socketChannel.socket().setReuseAddress(true);  
  40.             socketChannel.connect(socketAddress);  
  41.         } catch (ClosedChannelException e) {  
  42.             logger.warn("Channel is closed: ClosedChannelException");  
  43.         } catch (IOException e) {  
  44.             logger  
  45.                     .warn("Connet is failed or time out,the system will automatically re-connected : IOException");  
  46.         }  
  47.     }  
  48.   
  49.     /** 
  50.      * do ClientBuilder if socket conncte success 
  51.      */  
  52.     public void socketConnet() {  
  53.         try {  
  54.             openSocketChannel();  
  55.             if (socketChannel.isOpen()) {  
  56.                 this.stop = true;  
  57.                 socketBuilder();  
  58.                 socketChannel.configureBlocking(false);  
  59.                 socketChannel.register(selector, SelectionKey.OP_READ  
  60.                         | SelectionKey.OP_WRITE);  
  61.                 PackageBuilder clientBuilder = new PackageBuilder(socketChannel,  
  62.                         selector);  
  63.                 clientBuilder.start();  
  64.                 logger.info("Has been successfully connected to " + ip  
  65.                         + "and port:    " + port);  
  66.             } else {  
  67.                 socketChannel.close();  
  68.             }  
  69.         } catch (ClosedChannelException e) {  
  70.             logger.warn("Channel is closed: ClosedChannelException");  
  71.         } catch (IOException e) {  
  72.             logger  
  73.                     .warn("Connet is failed or time out,the system will automatically re-connected : IOException");  
  74.         }  
  75.   
  76.     }  
  77. }  

 发送和接收事件处理,NIO是基于事件的驱动模型,这个类就是专门处理收发的。

Java代码   收藏代码
  1. public class PackageBuilder  extends Thread{  
  2.     private SocketChannel socketChannel = null;  
  3.     private Selector selector = null;  
  4.     private boolean stop = false;  
  5.     private byte[] array = new byte[1024];  
  6.     private ByteBuffer byteBuffer;  
  7.     private PackageQueue packageQueue;  
  8.     private Logger logger = Logger.getLogger(PackageBuilder.class);  
  9.       
  10.     public PackageBuilder(SocketChannel socketChannel,Selector selectore){  
  11.         this.socketChannel = socketChannel;  
  12.         this.selector = selectore;  
  13.         packageQueue=new PackageQueue();  
  14.     }  
  15.     public void run(){  
  16.         try {  
  17.             while (!stop) {  
  18.                 Thread.sleep(1);  
  19.                 if(!socketChannel.isOpen()){  
  20.                     reconnect();//通道没打开或者断开执行重连工作(Channel did not open the work of the implementation of re-connection )  
  21.                     break;  
  22.                 }  
  23.                 if (selector.select(30) > 0) {  
  24.                     doSelector();  
  25.                 }  
  26.             }  
  27.         } catch (IOException e) {  
  28.             logger.error("CameraBuilder run error: IOException");  
  29.         } catch (InterruptedException e){  
  30.             logger.error("CameraBuilder run error: InterruptedException");  
  31.         }  
  32.     }  
  33.     public void doSelector(){  
  34.         for(SelectionKey key:selector.selectedKeys()){  
  35.             selector.selectedKeys().remove(key);  
  36.             if(!key.isValid()){  
  37.                 continue;  
  38.             }  
  39.             doKeys(key);  
  40.         }  
  41.     }  
  42.       
  43.     public void doKeys(SelectionKey key){  
  44.         SocketChannel channel = (SocketChannel)key.channel();  
  45.         if(key.isReadable()){  
  46.             readResponse(channel);  
  47.         }  
  48.         if(key.isWritable()){  
  49.             sendRequest(channel);  
  50.         }  
  51.     }  
  52.     private void readResponse(SocketChannel channel) {  
  53.         byteBuffer=ByteBuffer.wrap(array);  
  54.         byteBuffer.clear();  
  55.         int count = 0;  
  56.         try {  
  57.             count = channel.read(byteBuffer);  
  58.         } catch (IOException e) {  
  59.             reconnect();//通道没打开或者断开执行重连工作(Channel did not open the work of the implementation of re-connection )  
  60.             logger.error("Connection reset by peer: IOException");  
  61.         }  
  62.         if(count != -1){  
  63.             byteBuffer.flip();  
  64.             byte[] bs = new byte[count];  
  65.             byteBuffer.get(bs);  
  66.             ByteBuffer returnBuffer = ByteBuffer.allocate(count);  
  67.             returnBuffer.clear();  
  68.             returnBuffer.put(bs);  
  69.             returnBuffer.flip();  
  70.             PrintUtil.printBf(returnBuffer.array());  
  71.             ParseBufferData parseData=new ParseBufferData(returnBuffer);          
  72.             parseData.parseBuffer();              
  73.       }  
  74.         if(count < 0){  
  75.             reconnect();  
  76.         }  
  77.     }  
  78.     /** 
  79.      * send pakcet of request 
  80.      * @param channel 
  81.      */  
  82.     public void sendRequest(SocketChannel channel){  
  83.         byte[] array = packageQueue.takeMsgs();  
  84.         if(array!=null){  
  85.         ByteBuffer byteBuffer = ByteBuffer.wrap(array);  
  86.             try {  
  87.                 channel.write(byteBuffer);  
  88.              } catch (IOException e) {  
  89.                  reconnect();//通道没打开或者断开执行重连工作(Channel did not open the work of the implementation of re-connection )  
  90.                 logger.warn("socket not connected or has been closed: IOException");  
  91.              }  
  92.          }  
  93.     }  
  94.       
  95.     public void reconnect(){  
  96.         stopClient();  
  97.         logger.warn("socket not connected or has been closed");  
  98.         ThreadPoolUtil.getExecutor().execute(new CameraSocket());  
  99.     }  
  100.       
  101.     public void stopClient(){  
  102.         this.stop = true;  
  103.         if(socketChannel.isConnected() && !socketChannel.isOpen()){  
  104.             try {  
  105.                 socketChannel.close();  
  106.                 logger.info("server_socket has connected");  
  107.             } catch (IOException e) {  
  108.                 logger.warn("Channel closed to failed: IOException");  
  109.             }  
  110.         }  
  111.     }  
  112. }  

 发送和接收数据存放在缓存中

Java代码   收藏代码
  1. public class PackageQueue {  
  2.     private static  List<byte[]> queue = new ArrayList<byte[]>();  
  3.       
  4.     public PackageQueue(){    
  5.     }  
  6.       
  7.     public void pushMsgs(byte[] array){  
  8.         synchronized(queue){  
  9.             queue.add(array);  
  10.         }  
  11.     }  
  12.       
  13.     public byte[] takeMsgs() {  
  14.         synchronized (queue) {  
  15.             byte[] sd=null;  
  16.             if(queue != null){  
  17.                 if(queue.size() > 0){  
  18.                     sd = queue.get(0);  
  19.                     queue.remove(0);  
  20.                 }  
  21.             }  
  22.             return sd;  
  23.         }  
  24.           
  25.     }  
  26.   
  27.     public static List<byte[]> getQueue() {  
  28.         return queue;  
  29.     }  
  30.   
  31.     public static void setQueue(List<byte[]> queue) {  
  32.         PackageQueue.queue = queue;  
  33.     }  
  34. }  


public class CameraSocket extends Thread {
    private int cmdPort = SocketInfoUtils.CMD_PORT; // 5554
    private String host = SocketInfoUtils.HOST; // 172.16.163.38
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    //	DatagramChannel dataChannel;
    DatagramChannel cmdChannel;
    Selector selector;
    CameraQueue cameraQueue;

    public CameraSocket() throws Exception {
        selector = Selector.open();
        cameraQueue = new CameraQueue();
        cmdChannel = DatagramChannel.open();
        cmdChannel.configureBlocking(false);
        SocketAddress target = new InetSocketAddress(host, cmdPort);
        cmdChannel.connect(target);
        cmdChannel.register(selector, SelectionKey.OP_WRITE);
    }

    @Override
    public void run() {
        boolean flag = true;
        while (flag) {
            try {
                doSelector();
            } catch (IOException e) {
                flag = false;
                e.printStackTrace();
            }
        }
    }

    private void doSelector() throws IOException {
        if (selector.select(1000) > 0) {
            for (SelectionKey key : selector.selectedKeys()) {
                if (key.isWritable()) {
                    writeEvent(cmdChannel);
                }
            }
            selector.selectedKeys().clear();
        }
    }

//	private void readEvent(SelectionKey key) throws IOException {
//	ByteBuffer buffer = ByteBuffer.allocate(1024);
//	dataChannel.receive(buffer);
//	buffer.flip();
//	ParseBufferData parseBufferData=new ParseBufferData(buffer);
//	parseBufferData.parseBuffer();
//	}

    private void writeEvent(DatagramChannel channel) throws IOException {
        byte[] array = cameraQueue.takeMsgs();
        if (array != null) {
            ByteBuffer byteBuffer = ByteBuffer.wrap(array);
            try {
                channel.write(byteBuffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

public class SocketInfoUtils {

    public static Properties factory = SocketPropertiesFactory.getInstance().getBoundle();
    public static String TCP_IP = factory.getProperty("tcp_ip");
    public static int TCP_PORT = Integer.parseInt(factory.getProperty("tcp_port"));
    public static int CAMERA_PORT=Integer.parseInt(factory.getProperty("camera_port"));

    //public static int UDP_PORT = Integer.parseInt(factory.getProperty("udp_port"));
    public static int HIS_UDP_PORT = Integer.parseInt(factory.getProperty("his_udp_port"));

    public static int CMD_PORT = Integer.parseInt(factory.getProperty("cmd_port"));
    public static int DATA_PORT = Integer.parseInt(factory.getProperty("data_port"));
    public static final String HOST = factory.getProperty("host");
}
public class ThreadPoolUtil {

    private static ThreadPoolExecutor executor;
    static{
        BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(1);
        executor = new ThreadPoolExecutor(5,100,500,TimeUnit.MILLISECONDS,queue);
        RejectedExecutionHandler rejected = new RejectedExecutionHandler() {
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println(String.format("======= Task %d rejected.======", r.hashCode()));
            }
        };
        executor.setRejectedExecutionHandler(rejected);
    }

    public static ThreadPoolExecutor getExecutor() {
        return executor;
    }

    public static void setExecutor(ThreadPoolExecutor executor) {
        ThreadPoolUtil.executor = executor;
    }

}




 以上就是客户端连接、发送、接收的代码。希望对大家有所帮助

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值