/* * Sun Public License * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is available at http://www.sun.com/ * * The Original Code is the SLAMD Distributed Load Generation Engine. * The Initial Developer of the Original Code is Neil A. Wilson. * Portions created by Neil A. Wilson are Copyright (C) 2004-2010. * Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): Neil A. Wilson */ package com.slamd.tools.throughputtest; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; /** * This program defines a multithreaded server that will accept connections from * clients and will then spew a sequence of bytes to that client as quickly as * possible. The client is responsible for accepting that data and keeping * track of how much it received. The server will continue to provide data to * the client until the client disconnects. * * * @author Neil A. Wilson */ public class ThroughputTestServer { /** * The default buffer size to use in bytes. */ public static final int DEFAULT_BUFFER_SIZE = 8192; /** * The default port on which to listen for connections. */ public static final int DEFAULT_LISTEN_PORT = 3333; // Indicates whether to use TCP_NODELAY when sending data to the client. protected boolean useTCPNoDelay; // The size of the buffer size to use when sending data to the client. protected int bufferSize; // The port on which the server will listen for connections from clients. private int listenPort; /** * Parses the command-line arguments and invokes the constructor with the * appropriate values. * * @param args The command-line arguments provided to this program. */ public static void main(String[] args) { boolean useTCPNoDelay = false; int bufferSize = DEFAULT_BUFFER_SIZE; int listenPort = DEFAULT_LISTEN_PORT; for (int i=0; i < args.length; i++) { if (args[i].equals("-b")) { bufferSize = Integer.parseInt(args[++i]); } else if (args[i].equals("-p")) { listenPort = Integer.parseInt(args[++i]); } else if (args[i].equals("-N")) { useTCPNoDelay = true; } else if (args[i].equals("-H")) { displayUsage(); System.exit(0); } else { System.err.println("Unrecognized argument \"" + args[i]); displayUsage(); System.exit(1); } } ThroughputTestServer throughputServer = new ThroughputTestServer(listenPort, bufferSize, useTCPNoDelay); try { throughputServer.handleClients(); } catch (IOException ioe) { System.err.println("Unable to listen for client connections: " + ioe); ioe.printStackTrace(); System.exit(1); } } /** * Creates a new instance of the throughput test server with the provided * information. * * @param listenPort The TCP port on which the server should listen for * connections from clients. * @param bufferSize The buffer size in bytes to use when sending data to * the clients. * @param useTCPNoDelay Indicates whether to use TCP_NODELAY when sending * data to the client. */ public ThroughputTestServer(int listenPort, int bufferSize, boolean useTCPNoDelay) { this.listenPort = listenPort; this.bufferSize = bufferSize; this.useTCPNoDelay = useTCPNoDelay; } /** * Creates a server socket to accept client connections and then operates in * an infinite loop, accepting new connections and handing them off to worker * threads to be handled. * * @throws IOException If a problem occurs while creating the server socket * to accept the client connections. */ public void handleClients() throws IOException { ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.socket().bind(new InetSocketAddress(listenPort)); serverChannel.configureBlocking(true); System.out.println("Listening on port " + listenPort + " for client connections"); while (true) { try { SocketChannel clientChannel = serverChannel.accept(); new ThroughputTestServerThread(this, clientChannel).start(); } catch (Exception e) { System.err.println("Error accepting client connection: " + e); e.printStackTrace(); } } } /** * Displays usage information for this program. */ public static void displayUsage() { String EOL = System.getProperty("line.separator"); System.err.println( "Usage: java ThroughputTestServer [options]" + EOL + " where [options] include:" + EOL + "-b [size] -- Specifies the buffer size to use in bytes (default is " + DEFAULT_BUFFER_SIZE + ')' + EOL + "-p [port] -- Specifies the port on which to listen for clients (default is " + DEFAULT_LISTEN_PORT + ')' + EOL + "-N -- Indicates that TCP_NODELAY should be used when sending data" + EOL + "-H -- Displays this usage information" ); } }