非阻塞模式 Socket 连接

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;


class Target {
    
    InetSocketAddress address;
    SocketChannel channel;
    Exception failure;
    long connectStart;
    long connectFinish = 0;
    boolean shown = false;
    
    Target(String host) {
        try {
            address = new InetSocketAddress(InetAddress.getByName(host), 80);
        }
        catch (IOException e) {
            failure = e;
        }
    }
    
    void show() {
        String result;
        if(connectFinish != 0) {
            result = Long.toString(connectFinish - connectStart) + "ms";
         }
        else if(failure != null) {
            result = failure.toString();
        }
        else {
            result = "Timed out";
        }
        System.out.println(address + ":" + result);
        shown = true;
    }
}


public class PingClient {

    private Selector selector;
    private LinkedList<Target> targets = new LinkedList<Target>();
    private LinkedList<Target> finishedTargets = new LinkedList<Target>();
    
    boolean shutdown = false;
    
    public PingClient() throws IOException {
        
        selector = Selector.open();
        Connector connector = new Connector();
        Printer printer = new Printer();
        connector.start();
        printer.start();
        receiveTarget();
        
    }
    
    
    public static void main(String[] args) throws IOException {
        
        new PingClient();
    }
    
    
    public void addTarget(Target target) {
        
        SocketChannel socketChannel = null;
        try {
            socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.connect(target.address);
            
            target.channel = socketChannel;
            target.connectStart = System.currentTimeMillis();
            
            synchronized(targets) {
                targets.add(target);
            }
            selector.wakeup();
            
        }
        catch (Exception e) {
            if(socketChannel != null) {
                try {
                    socketChannel.close();
                }
                catch (IOException ex) {
                    
                }
            }
            target.failure = e;
            addFinishedTarget(target);
        }
    }
    
    
    public void addFinishedTarget(Target target) {
        
        synchronized(finishedTargets) {
            finishedTargets.notify();
            finishedTargets.add(target);
        }
    }
    
    
    public void printFinishedTargets() {
        
        try {
            for(;;) {
                Target target = null;
                synchronized(finishedTargets) {
                    while(finishedTargets.size() == 0){
                        finishedTargets.wait();
                    }
                    target = (Target) finishedTargets.removeFirst();
                }
                target.show();
            }
        }
        catch (InterruptedException e) {
            return;
        }
    }
    
    
    public void registerTargets() {
        
        synchronized(targets) {
            while(targets.size() > 0) {
                Target target = (Target) targets.removeFirst();
                
                try {
                    target.channel.register(selector, SelectionKey.OP_CONNECT, target);
                }
                catch (IOException e) {
                    try {
                        target.channel.close();
                    }
                    catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    target.failure = e;
                    addFinishedTarget(target);
                }
            }
        }
    }
    
    
    public void processSelectedKeys() {
        
        for(Iterator<SelectionKey> it = selector.selectedKeys().iterator(); it.hasNext();) {
            SelectionKey selectionKey = it.next();
            it.remove();
            
            Target target = (Target) selectionKey.attachment();
            SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
            
            try {
                if(socketChannel.finishConnect()) {
                    selectionKey.cancel();
                    target.connectFinish = System.currentTimeMillis();
                    socketChannel.close();
                    addFinishedTarget(target);
                }
            }
            catch (IOException e) {
                try {
                    socketChannel.close();
                }
                catch (IOException ex) {
                    ex.printStackTrace();
                }
                target.failure = e;
                addFinishedTarget(target);
            }
        }
    }
    
    
    public void receiveTarget() {
        
        try {
            BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
            String host = null;
            while((host = localReader.readLine()) != null) {
                if(!host.equals("bye")) {
                    Target target = new Target(host);
                    addTarget(target);
                }
                else {
                    shutdown = true;
                    selector.wakeup();
                    break;
                }
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    
    public class Printer extends Thread {
        
        public Printer() {
            setDaemon(true);
        }
        
        public void run() {
            printFinishedTargets();
        }
    }
    
    
    public class Connector extends Thread {
        
        public void run() {
            while(! shutdown) {
                try {
                    registerTargets();
                    if(selector.select() > 0) {
                        processSelectedKeys();
                    }
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
            try {
                selector.close();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

posted on 2014-11-27 10:18  starzou  阅读(358)  评论(0编辑  收藏  举报

导航