- jock.java
Listings
- ^ jock.java
-
package net.dougharris.utility;
import net.dougharris.utility.jockmods.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.IOException;
public class jock{
static String options="?-k-A-e-i-o-s-S-v-V-y-b_n_N_c_C_O_I_p_P_h_H_d_D_r_R_w_W_l-L_E_";
static P cmdArgs;
static StringBuffer cmdLine;
/* configuration variables */
static boolean echo;
static boolean server;
static boolean source;
static boolean serverSource;
static boolean useStdin;
static String inFileName;
static boolean useStdout;
static String outFileName;
static int operationCount;
static int operatorCount;
static int operatorNumber;
static Level logLevel;
/* timing variables */
static int startDelay;
static int spinDelay;
static int minConnectDelay;
static int maxConnectDelay;
static InetAddress serverHost;
static InetAddress clientHost;
static int serverPort;
static int clientPort;
static boolean noDelay;
static int soLinger;
static boolean keepAlive;
static int sizeRead;
static int sizeReadBuffer;
static int sizeWrite;
static int sizeWriteBuffer;
static int backlog;
static String processorClassName;
static Processor processor;
static Discard discard=new Discard();
Chargen chargen;
public static void help(){
P.rintln("[-s # serverMode][-S # sourceMode]");
P.rintln("[-e # echoMode][-E echoProcessor]");
P.rintln("[-h server][-H client]");
P.rintln("[-p serverPort][-P clientPort]");
P.rintln("[-i|-I inFileName] [-o|-O outFileName]");
P.rintln("[-v #light logging] [-V # heavy logging]");
P.rintln("[-l #log to stderr] [-L logFileName]");
P.rintln("[-r userReadSize][-R socketReadSize]");
P.rintln("[-w userWriteSize][-W socketWriteSize]");
P.rintln("[-n operationCount][-N operatorCount]");
P.rintln("[-d spinDelay][-D startDelay]");
P.rintln("[-c connections][-C connections]");
}
static class Client implements Runnable{
int whichOperator;
Socket clientSocket;
Client(){
try{
whichOperator=operatorNumber++;
clientSocket = new Socket();
setSocketArgs(clientSocket);
logSocketArgs(clientSocket);
clientSocket.bind(new InetSocketAddress(clientHost, clientPort));
clientSocket.connect(new InetSocketAddress(serverHost, serverPort));
} catch(IOException x){
throw new RuntimeException("Client constructor "+x);
}
}
public void start(){
new Thread(this).start();
}
public void run(){
try{
cmdArgs.config("client "+whichOperator+" socket connected.");
configureAndRun(clientSocket,whichOperator);
clientSocket.close();
cmdArgs.config("client "+whichOperator+" socket closed.");
}catch(IOException x){
throw new RuntimeException(x);
}
}
}
static class Server implements Runnable{
private int whichOperator;
private Socket serviceSocket;
Server(ServerSocket listenSocket) throws IOException{
whichOperator=operatorNumber++;
serviceSocket = listenSocket.accept();
cmdArgs.config("server "+whichOperator+" socket accepted.");
setSocketArgs(serviceSocket);
logSocketArgs(serviceSocket);
}
public void start(){
new Thread(this).start();
}
public void run(){
try{
configureAndRun(serviceSocket,whichOperator);
serviceSocket.close();
cmdArgs.config("server "+whichOperator+" socket closed.");
} catch (IOException x){
throw new RuntimeException(x);
}
}
}
static class Sender implements Runnable{
private Socket senderSocket;
private InputStream iUser;
private Thread runThread;
private byte[] bWrite;
int nWrite;
int tWrite;
long tWriteTime;
private int whichOperator;
OutputStream oNetwork;
Sender(Socket senderSocket, int whichOperator){
this.senderSocket=senderSocket;
this.whichOperator=whichOperator;
bWrite = new byte[sizeWrite];
try{
if(null!=cmdArgs.getProperty("-I")){
iUser=new FileInputStream(inFileName);
} else{
iUser=useStdin?System.in:new Chargen();
}
oNetwork = senderSocket.getOutputStream();
} catch(IOException x){
throw new RuntimeException("sender constructor "+x);
}
}
public void start(){
runThread = new Thread(this);
runThread.start();
}
public void run(){
cmdArgs.config("sender "+whichOperator+" starting.");
try{
P.ause(startDelay);
cmdArgs.fine(" starting Sender");
int iterationLimit=operationCount;
tWrite=0;
tWriteTime=-cmdArgs.now();
cmdArgs.fine("Original tWriteTime is "+tWriteTime);
for (int iterationCount=0;;iterationCount++){
if ((iterationLimit>0)&&(iterationCount==iterationLimit)) break;
if (-1==(nWrite=iUser.read(bWrite))) break;
tWrite+=nWrite;
cmdArgs.fine
(whichOperator+" iteration "+iterationCount
+" input to write "+nWrite+" total "+tWrite);
oNetwork.write(bWrite,0,nWrite);
P.ause(spinDelay);
}
tWriteTime+=P.now();
double ftWriteTime=tWriteTime/1000.0;
cmdArgs.fine("wrote "+tWrite+ " bytes in "+(ftWriteTime)+" s");
cmdArgs.fine("writing Bandwidth = "+(tWrite/(ftWriteTime))+" bytes/sec");
senderSocket.shutdownOutput();
cmdArgs.config("Sender "+whichOperator+" shutdownOutput.");
} catch(IOException x){
throw new RuntimeException(x);
}
}
}
static class Receiver implements Runnable{
private Socket receiverSocket;
private OutputStream oUser;
private Thread runThread;
private int whichOperator;
InputStream iNetwork;
Receiver(Socket receiverSocket, int whichOperator){
this.receiverSocket=receiverSocket;
this.whichOperator=whichOperator;
try{
if(null!=cmdArgs.getProperty("-O")){
oUser=new FileOutputStream(outFileName);
} else{
oUser = useStdout?(OutputStream)System.out:discard;
}
iNetwork = receiverSocket.getInputStream();
} catch(IOException x){
throw new RuntimeException("receiver constructor ",x);
}
}
public void start(){
runThread = new Thread(this);
runThread.start();
}
public void join(){
try{runThread.join();}catch(InterruptedException ignored){}
}
public void run(){
cmdArgs.config("Receiver" +whichOperator+" run.");
byte[] bRead = new byte[sizeRead];
int nRead;
int tRead;
long tReadTime;
try{
int iterationLimit=operationCount;
P.ause(startDelay);
tRead=0;
tReadTime= -cmdArgs.now();
for (int iterationCount=0;;iterationCount++){
if ((iterationLimit>0)&&(iterationCount==iterationLimit)) break;
if (-1==(nRead=iNetwork.read(bRead))) break;
tRead+=nRead;
cmdArgs.fine
(whichOperator+" iteration "+iterationCount+" read "+nRead+" total "+tRead);
oUser.write(bRead,0, nRead);
P.ause(spinDelay);
}
tReadTime+=P.now();
double ftReadTime=tReadTime/1000.0;
cmdArgs.fine("read "+tRead+ " bytes in "+(ftReadTime)+" s");
cmdArgs.config("Receiver "+whichOperator+" shutdown.");
cmdArgs.fine("reading Bandwidth = "+(tRead/(ftReadTime))+" bytes/sec");
} catch(IOException x){
throw new RuntimeException(x);
}
}
}
static class ProcessIO implements Runnable{
private Socket processSocket;
private InputStream i;
private OutputStream o;
private int whichOperator;
private ProcessIO(Socket processSocket, int whichOperator){
this.processSocket=processSocket;
this.whichOperator=whichOperator;
try{
this.i=processSocket.getInputStream();
this.o=processSocket.getOutputStream();
} catch(IOException x){
throw new RuntimeException(x);
}
}
public void start(){
(new Thread(this)).start();
}
public void run(){
processor = (Processor) P.getInstance(processorClassName);
cmdArgs.config(whichOperator+" run processor.");
try{
processor.process(i,o);
processSocket.shutdownOutput();
cmdArgs.config("Processor "+whichOperator+" shutdownOutput.");
} catch(IOException x){
throw new RuntimeException(x);
} catch(ProcessorException x){
throw new RuntimeException(x);
}
}
}
public static void main(String[] args){
cmdArgs = P.arseArgs(options,args);
cmdLine=new StringBuffer();
cmdLine.append("\"jock");
for (int i=0;i<args.length;i++){
cmdLine.append(" ");
cmdLine.append(args[i]);
}
cmdLine.append("\" ");
setLogging();
setArgs();
setNames();
if (cmdArgs.getFlag("-?")){
help();
P.exit(0);
}
if (server){
Listen();
} else {
Connect();
}
}
/**
* java.util.logging.Level has 7 levels plus the extremes of NONE and ALL.
* jock uses four of these levels internally,
* and uses the -v and -V flags to set them.
* The default logging if no flags are specified is SEVERE.
* In the jock code this level is accomplished with the severe() method.
* This is only used just before throwing a RuntimeException.
* For a moderate amount of logging, limited to basic information
* only, the -v flag by itself produces Level.INFO logging.
* In the jock code this level is accomplished with the info() method.
* If you would like logging up through addressing, and creating objects,
* the -V flag produces CONFIG level logging, done in the code with config().
* Finally, the finest logging that the jock code itself performs is specified
* using both flags -v and -V, and done in the code by fine().
*
* You may wish to send the logging information to a file, rather than
* to the default standard error stream, and this is done by giving the
name of that file as the value of the property -L.
*/
static void setLogging(){
logLevel=Level.SEVERE;
boolean logInfo = cmdArgs.getFlag("-v");
boolean logFine = cmdArgs.getFlag("-V");
if (!logFine){
if (logInfo){ // -v
logLevel=Level.INFO;
}
} else { // logFine
if (!logInfo){ // -V
logLevel=Level.CONFIG;
} else { // -v -V
logLevel=Level.FINE;
}
}
cmdArgs.setLogLevel(logLevel);
if (null!=cmdArgs.getProperty("-L")){
String logFileName=cmdArgs.getProperty("-L");
cmdArgs.setLogFile(logFileName);
}
}
static void setArgs(){
cmdArgs.info("cmdline "+cmdLine);
server = cmdArgs.getFlag("-s");
cmdArgs.info("server "+server);
echo = cmdArgs.getFlag("-e");
cmdArgs.info("echo "+echo);
serverSource = cmdArgs.getFlag("-S");
cmdArgs.info("serverSource "+serverSource);
source=!server^serverSource;//either both false or both true
sizeRead = cmdArgs.getIntProperty("-r",1024);
sizeWrite = cmdArgs.getIntProperty("-w",1024);
sizeReadBuffer = cmdArgs.getIntProperty("-R",0);
sizeWriteBuffer = cmdArgs.getIntProperty("-W",0);
useStdin = cmdArgs.getFlag("-i");
inFileName = cmdArgs.getProperty("-I");
if (null!=inFileName){
useStdin=true;
}
useStdout = cmdArgs.getFlag("-o");
outFileName = cmdArgs.getProperty("-O");
startDelay = cmdArgs.getIntProperty("-D",0);
spinDelay = cmdArgs.getIntProperty("-d",0);
minConnectDelay = cmdArgs.getIntProperty("-c",0);
maxConnectDelay = cmdArgs.getIntProperty("-C",0);
operationCount = cmdArgs.getIntProperty("-n",0);
operatorCount = cmdArgs.getIntProperty("-N",1);
backlog = cmdArgs.getIntProperty("-b" ,5);
processorClassName = cmdArgs.getProperty("-E","net.dougharris.utility.jockmods.EchoProcessor");
if (null!=cmdArgs.getProperty("-E")){
echo=true;
}
if (useStdin&&(null==cmdArgs.getProperty("-n"))){
operationCount=0;
}
}
static void setSocketArgs(Socket s) throws SocketException{
if (cmdArgs.getFlag("-y")){
s.setTcpNoDelay(true);
}
cmdArgs.fine(" noDelay "+s.getTcpNoDelay());
if (cmdArgs.getFlag("-k")){
s.setKeepAlive(true);
}
cmdArgs.fine(" keepalive "+s.getKeepAlive());
/* THIS IS VERY WRONG: trying to set property linger, not what -l is for
if (null!=cmdArgs.getProperty("-l")){
soLinger = cmdArgs.getIntProperty("-l",0);
s.setSoLinger(true, soLinger);
}
cmdArgs.fine(" linger "+s.getSoLinger());
*/
if (null!=cmdArgs.getProperty("-W")){
s.setSendBufferSize(sizeWriteBuffer);
cmdArgs.fine(" request send Buffer "+sizeWriteBuffer);
}
if (null!=cmdArgs.getProperty("-R")){
s.setReceiveBufferSize(sizeReadBuffer);
cmdArgs.fine(" request receive Buffer "+sizeReadBuffer);
}
}
static void logSocketArgs(Socket s) throws SocketException{
cmdArgs.config("send buffer size:"+s.getSendBufferSize());
cmdArgs.config("receive buffer size:"+s.getReceiveBufferSize());
}
static void setServerSocketArgs(ServerSocket s) throws SocketException{
if (null!=cmdArgs.getProperty("-R")){
s.setReceiveBufferSize(sizeReadBuffer);
}
}
static void setNames(){
try{
InetAddress local=InetAddress.getLocalHost();
//JDH
//JDH On client clientHost is localHost
//JDH On server clientHost is remoteHost
//JDH On client serverHost is remoteHost
//JDH On server serverHost is remoteHost
//JDH
String localName=local.getHostName();
String serverName = (cmdArgs.getProperty("-h",localName));
serverHost = InetAddress.getByName(serverName);
serverPort = cmdArgs.getIntProperty("-p",8888);
String clientName = (cmdArgs.getProperty("-H",server?null:localName));
clientHost = InetAddress.getByName(clientName);
clientPort = cmdArgs.getIntProperty("-P", 0);
//System.err.println(">>>>> clientHost <<<<<<<"+ clientHost);
//System.err.println(">>>>> clientPort <<<<<<<"+ clientPort);
//System.err.println(">>>>> serverHost <<<<<<<"+serverHost);
//System.err.println(">>>>> serverPort <<<<<<<"+serverPort);
cmdArgs.config("server address "+serverHost+":"+serverPort);
cmdArgs.config("client address "+clientHost+":"+clientPort);
} catch (UnknownHostException x){
P.exception(x,1);
} catch (NumberFormatException x){
P.exception(x,1);
}
}
static void configureAndRun(Socket s, int whichOperator) throws IOException{
if (!source){ //this object is not to be the source
if(echo){
new ProcessIO(s, whichOperator).run();
} else {
new Receiver(s, whichOperator).run();
}
} else { // this object is to be the source
Receiver r=null;
if (echo){
r=new Receiver(s,whichOperator);
r.start();
}
new Sender(s,whichOperator).run();
if (r!=null){
r.join();
}
}
}
static void Listen(){
ServerSocket listenSocket;
Socket serviceSocket;
int serverSpawned=0;
boolean shouldRun = true;
cmdArgs.config("Running as Listen()");
try{
listenSocket = new ServerSocket(serverPort, backlog, serverHost);
setServerSocketArgs(listenSocket);
if (!cmdArgs.getFlag("-N")){
new Server(listenSocket).run();
} else {
while(shouldRun){
if ((operatorCount>0)&&((++serverSpawned)>=operatorCount)){
break;
}
new Server(listenSocket).start();
}
}
listenSocket.close();
}catch (IOException x){
throw new RuntimeException(x);
}
}
/**
* This is called to handle Connections, thus from a client,
* which for jock is equivalent to not having the -s flag set.
* If the -N propery is not specified then it makes a single connection
* and when that is completed it dies. If that property is specified
* with the value 0 then it keeps making connections at a rate
* specified by the combined values of the -c/-C properties (what
* is the default). Otherwise it spawns the specified number of threads,
* at the specified rate.
**/
static void Connect(){
cmdArgs.config("Running Connector");
if (!cmdArgs.getFlag("-N")){
new Client().run();
} else {
for(int clientsSpawned=0;;clientsSpawned++){
if ((operatorCount>0)&&(clientsSpawned >= operatorCount)){
break;
}
P.ause(minConnectDelay,maxConnectDelay);
new Client().start();
}
}
}
}
|