Package

Source Code of MakeIdleHttpConnection

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.Set;

// makeup idle keep-alive HTTP connection, and periodly close and re-open the connection

class PendingClose implements Comparable<PendingClose> {
    public final SelectionKey key;
    public final long closeTime;

    public PendingClose(SelectionKey key, long closeTime) {
        this.key = key;
        this.closeTime = closeTime;
    }

    public int compareTo(PendingClose o) {
        return (int) (closeTime - o.closeTime);
    }

    public String toString() {
        return "PendingClose [key=" + key + ", closeTime=" + closeTime + "]";
    }

}

public class MakeIdleHttpConnection {
    // config
    static int CONCURENCY = 4000;
    final static int PORT = 4348;
    // local test, a computer can have many ips
    final static InetSocketAddress ADDRS[] = { new InetSocketAddress("127.0.0.1", PORT), };
    final static byte[] REQUEST = "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n".getBytes();

    // status
    static int opened = 0;
    static int connected = 0;

    public static int randIdleTime() {
        return r.nextInt(1000 * 40) + 1000 * 8;
    }

    // helper
    final static Random r = new Random();
    final static ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 64);
    static Selector selector;

    // close and reopen the connection after a time
    final static PriorityQueue<PendingClose> pendingClose = new PriorityQueue<PendingClose>();

    public static void handlePendingClose() throws IOException {
        long now = System.currentTimeMillis();
        PendingClose p;
        while ((p = pendingClose.peek()) != null) {
            if (p.closeTime < now) {
                close(p.key.channel());
                pendingClose.poll();
            } else {
                break;
            }
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        if (args.length > 0) {
            CONCURENCY = Integer.parseInt(args[0]);
        }
        selector = Selector.open();

        long start = System.currentTimeMillis();
        long lastPrintTime = 0;
        while (true) {
            long now = System.currentTimeMillis();
            if (now - start > 1000 * 60 * 20) {
                // exits after 20 minutes
                break;
            }

            for (int i = 0; i < 20 && connected < CONCURENCY; ++i) {
                for (InetSocketAddress addr : ADDRS) {
                    connect(addr);
                }
            }
            int select = selector.select(2000); // 2s

            handlePendingClose();
            if (select <= 0) {
                continue;
            }

            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> it = selectedKeys.iterator();

            while (it.hasNext()) {
                SelectionKey key = it.next();
                SocketChannel ch = (SocketChannel) key.channel();
                if (key.isConnectable()) {
                    try {
                        if (ch.finishConnect()) {
                            ++connected;
                            key.interestOps(SelectionKey.OP_WRITE);
                        }
                    } catch (Exception e) {
                        ch.close();
                    }
                } else if (key.isWritable()) {
                    // should write all, TCP buffer
                    ch.write(ByteBuffer.wrap(REQUEST));
                    key.interestOps(SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    buffer.clear();
                    try {
                        int read = ch.read(buffer);
                        if (read == -1) {
                            close(ch); // remote closed cleanly
                        } else {
                            key.cancel(); // not selectalbe
                            pendingClose.add(new PendingClose(key, now + randIdleTime()));
                        }
                    } catch (Exception e) {
                        close(ch);
                    }
                }
            }
            selectedKeys.clear();
            Thread.sleep(20);
            if (now - lastPrintTime >= 1000) {
                lastPrintTime = now;
                System.out
                        .println("connection opened: " + opened + "; connected: " + connected);
            }
        }
    }

    public static void close(SelectableChannel ch) {
        connected--;
        try {
            ch.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void connect(InetSocketAddress addr) throws IOException, SocketException,
            ClosedChannelException {
        opened++;
        SocketChannel ch = SocketChannel.open();
        ch.configureBlocking(false);
        ch.socket().setReuseAddress(true);
        ch.register(selector, SelectionKey.OP_CONNECT);
        ch.connect(addr);
    }
}
TOP

Related Classes of MakeIdleHttpConnection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.