0

Awhile ago I created a program that created socket connections and funneled their input to a single telnet connection to our legacy server. The goal of the project is to create a front end for the legacy database and eventually move to a modern database. I set it up in a way that I thought I would be able to scale out to multiple telnet connections. Well now it's time for me to start using 2-4 connections to the legacy server and it doesn't work. It always sends input to the last connection made. Here's what I've done:

Class 1 - ServerConsole

package serverconsole;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

/**
 *
 * @author Andrew
 */
public class ServerConsole {

    public static ArrayList<Boolean> busy = new ArrayList();
    public static ArrayList<MvTelnet> telnet = new ArrayList();
    static final Logger log = Logger.getLogger("errors");
    static FileHandler fh;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(5500)) {
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
                @Override
                public void run() {
                    if (serverSocket != null) {
                        try {
                            serverSocket.close();
                        } catch (IOException ex) {
                            Logger.getLogger(ServerConsole.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }, "Shutdown-thread"));

            fh = new FileHandler("/mnt/javaprograms/ServerConsole/errors.log");
            log.addHandler(fh);
            SimpleFormatter formatter = new SimpleFormatter();
            fh.setFormatter(formatter);

            for(int i=0; i<2; i++) {
                busy.add(false);
                telnet.add(null);
            }

            while (true) {
                new MultiServerThread(serverSocket.accept()).start();
            }
        } catch (IOException e) {
            System.err.println(e);
            System.exit(-1);
        }
    }

    public static void log(String str) {
        log.info(str);
    }
}

Class 2 - MultiServerThread

package serverconsole;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/**
 *
 * @author Andrew
 */
public class MultiServerThread extends Thread {

    private Socket socket = null;

    public MultiServerThread(Socket socket) throws IOException {
        super("MultiServerThread");
        this.socket = socket;
    }

    @Override
    public void run() {
        try (
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))
            ;) {
            String input, output;
            while (true) {
                input = in.readLine();
                if (input.equals("Close")) {
                    break;
                }
                boolean written = false;
                while(written == false) {
                    for (int i=0;i < ServerConsole.busy.size(); i++) {
                        if (ServerConsole.busy.get(i) == false) {
                            ServerConsole.busy.set(i, true);
                            if (ServerConsole.telnet.get(i) == null) {
                                ServerConsole.telnet.set(i, new MvTelnet());
                            }
                            String response = ServerConsole.telnet.get(i).write(input);
                            out.println(response);
                            written = true;
                            ServerConsole.busy.set(i, false);
                            break;
                        }
                    }
                }
            }
            socket.close();
        } catch (IOException e) {
            ServerConsole.log(e.getMessage());
        }
    }
}

Class 3 - MvTelnet package serverconsole;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.apache.commons.net.telnet.EchoOptionHandler;
import org.apache.commons.net.telnet.InvalidTelnetOptionException;
import org.apache.commons.net.telnet.SuppressGAOptionHandler;
import org.apache.commons.net.telnet.TelnetClient;
import org.apache.commons.net.telnet.TerminalTypeOptionHandler;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;

/**
 *
 * @author Andrew
 */
public class MvTelnet {
    static TelnetClient tc = null;
    private static DataInputStream in = null;
    private static DataOutputStream out = null;
    static String response = null;
    static FileWriter fstream = null;
    static BufferedWriter bout = null;

    public MvTelnet() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("HH-mm-ss");
        try {
            tc = new TelnetClient();
            bout = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("/mnt/javaprograms/ServerConsole/log"+sdf.format(cal.getTime())+".txt"), "UTF-8"));
            TerminalTypeOptionHandler ttopt = new TerminalTypeOptionHandler("VT100", false, false, true, false);
            EchoOptionHandler echoopt = new EchoOptionHandler(true, false, true, false);
            SuppressGAOptionHandler gaopt = new SuppressGAOptionHandler(true, true, true, true);
            try {
                tc.addOptionHandler(ttopt);
                tc.addOptionHandler(echoopt);
                tc.addOptionHandler(gaopt);
            } catch (InvalidTelnetOptionException e) {
                ServerConsole.log(e.getMessage());
            }
            tc.connect("192.168.1.8", 2010);
            in = new DataInputStream(tc.getInputStream());
            out = new DataOutputStream(tc.getOutputStream());
            logon(true);
        } catch (IOException ex) {
            ServerConsole.log(ex.getMessage());
        }
    }

    public static String write(String command) throws IOException {
        command = command + "\n";
        byte[] comm = command.getBytes();
        out.write(comm);
        out.flush();
        response = in.readLine();
        bout.write(response+"\n");
        response = in.readLine();
        bout.write(response+"\n");
        if (response.contains("[] Connect time")) {
            logon(false);
            out.write(comm);
            out.flush();
            response = in.readLine();
            bout.write(response+"\n");
            response = in.readLine();
            bout.write(response+"\n");
        }
        bout.flush();
        return response;
    }

    public static void close() throws IOException {
        write("...\n");
        write("OFF\n");
        tc.disconnect();
    }

    private static void logon(boolean choice) throws IOException {
        String loginString = "JAVA-TRANS\n";
        byte[] logon = loginString.getBytes();
        if (choice == true) {
            response = in.readLine();
            bout.write(response+"\n");
            bout.flush();
            response = in.readLine();
            bout.write(response+"\n");
            bout.flush();
            out.write(logon);
            out.flush();
            response = in.readLine();
            bout.write(response+"\n");
            bout.flush();
            response = in.readLine();
            bout.write(response+"\n");
            bout.flush();
            if (!response.contains("OK")) {
                out.write(logon);
                out.flush();
                response = in.readLine();
                bout.write(response+"\n");
                bout.flush();
                while (!response.contains("OK")) {
                    response = in.readLine();
                    bout.write(response+"\n");
                    bout.flush();
                }
            }
            bout.flush();
        } else {
            out.write(logon);
            out.flush();
            out.write(logon);
            out.flush();
            while (!response.contains("OK")) {
                response = in.readLine();
                bout.write(response+"\n");
                bout.flush();
            }
        }
        bout.flush();
    }
}

I've since found Apaches common-pool library but I can't figure out how to implement it correctly while using my MvTelnet class as the object to pool. Is commons-pool the right way to go, and if so, how do i implement it?

EDIT: Alright I added all my code per a comment. I want to create a Pool of various MvTelnet objects that my sockets can send commands to. I don't have any of the Pool code in bc it was just a mess.

Andrew
  • 175
  • 1
  • 2
  • 12
  • Pool of what objects? Why? Where's the rest of the code? What's the question? – user207421 Jan 28 '15 at 18:21
  • @EJP - I added all my code. I'd like a pool of MvTelnet objects but I haven't been able to get commons-pool to do anything but throw me errors so that code's not there. – Andrew Jan 28 '15 at 20:13
  • 1
    A pool can help out here, see the [examples](http://commons.apache.org/proper/commons-pool/examples.html). You can leave `MvTelnet` as it is and create the pool in `ServerConsole` (replacing `telnet` and `busy`). In `MultiServerThread` call `ServerConsole.pool.borrowObject()` and `pool.returnObject`. Don't forget to close the pool when `ServerConsole` closes. – vanOekel Jan 28 '15 at 22:06

1 Answers1

0

If you want to create a client - server with multiple connections you have to use one thread by connection. When the connection is asked by a client, add a new thread which will handle input output for the new client.

Edit : You can use a limited number of thread if you want, just create a function that allocate new thread to the client if and only if there is a free place. example here

Thomas H
  • 81
  • 1
  • 8
  • I've looked that over and I'm not sure that's what I want...My program, right now, accepts multiple connections and takes their commands and funnels them through my telnet object to the legacy server. What I'm wanting is multiple telnet connections to the legacy server (which has to go through my MvTelnet class to parse all the junk for logging in). The number of connections to the legacy server has to be controlled btw. – Andrew Jan 28 '15 at 20:31