Multithreaded Server using TCP in Java

2019-08-16 01:05发布

问题:

I'm trying to implement a simple TCP connection between Client/Server. I made the Server multithreaded so that it can take either multiple requests (such as finding the sum, max, min of a string of numbers provided by the user) from a single client or accept multiple connections from different clients. I'm running both of them on my machine, but the server doesn't seem to push out an answer. Not sure what I'm doing wrong here --

public final class CalClient {

static final int PORT_NUMBER = 6789;  

public static void main (String arg[]) throws Exception
{
    String serverName;
    @SuppressWarnings("unused")
    String strListOfNumbers = null;
    int menuIndex;
    boolean exit = false;

    BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));

    System.out.println("Please enter host name...");
    System.out.print("> ");
    serverName = inFromUser.readLine();

    Socket clientSocket = new Socket(serverName, PORT_NUMBER);
    DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
    BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

    //outToServer.writeBytes(serverName + '\n');

    System.out.println("");
    System.out.println("Enter 1 to enter the list of numbers");
    System.out.println("Enter 2 to perform Summation");
    System.out.println("Enter 3 to calculate Maximum");
    System.out.println("Enter 4 to calculate Minimum");
    System.out.println("Enter 5 to Exit");

    while (!exit) {
        System.out.print(">");
        menuIndex = Integer.parseInt(inFromUser.readLine());

        if (menuIndex == 1) {   
            System.out.println("Please enter the numbers separated by commas.");
            System.out.print(">");
            strListOfNumbers = inFromUser.readLine();
            outToServer.writeBytes("List" + strListOfNumbers);
            //continue;
        }
        else if (menuIndex == 2) {
            outToServer.writeBytes("SUM");
            System.out.println(inFromServer.readLine());
        }
        else if (menuIndex == 3) {
            outToServer.writeBytes("MAX");
            System.out.println(inFromServer.readLine());
        }
        else if (menuIndex == 4) {
            outToServer.writeBytes("MIN");
            System.out.println(inFromServer.readLine());
        }
        else if (menuIndex == 5) {
            outToServer.writeBytes("EXIT");
            exit = true;
        }
    }
}

}

public final class CalServer 
{

      static final int PORT_NUMBER = 6789;  

public static void main(String[] args) throws IOException 
{
    try {
        ServerSocket welcomeSocket = new ServerSocket(PORT_NUMBER);
        System.out.println("Listening");
        while (true) {
            Socket connectionSocket = welcomeSocket.accept();

            if (connectionSocket != null) {
                CalRequest request = new CalRequest(connectionSocket);
                Thread thread = new Thread(request);
                thread.start();
            }
        }
    } catch (IOException ioe) {
        System.out.println("IOException on socket listen: " + ioe);
        ioe.printStackTrace();
    }
}
}

final class CalRequest implements Runnable
{
Socket socket;
BufferedReader inFromClient;
DataOutputStream outToClient;

TreeSet<Integer> numbers = new TreeSet<Integer>();
int sum = 0;

public CalRequest(Socket socket)
{
    this.socket = socket;
}

@Override
public void run() 
{
    try {
        inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
        outToClient = new DataOutputStream(socket.getOutputStream());

        while(inFromClient.readLine()!= null) {
            processRequest(inFromClient.readLine());
        }       

    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void processRequest(String string) throws IOException
{
    String strAction = string.substring(0,3);

    if (strAction.equals("LIS")) {
        String strNumbers = string.substring(5);
        String[] strNumberArr;
        strNumberArr = strNumbers.split(",");

        // convert each element of the string array to type Integer and add it to a treeSet container. 
        for (int i=0; i<strNumberArr.length; i++)
            numbers.add(new Integer(Integer.parseInt(strNumberArr[i])));
    }
    else if (strAction.equals("SUM")) {
        @SuppressWarnings("rawtypes")
        Iterator it = numbers.iterator();
        int total = 0;

        while (it.hasNext()) {
            total += (Integer)(it.next());
        }
    }
    else if (strAction.equals("MAX")) {
        outToClient.writeBytes("The max is: " + Integer.toString(numbers.last()));
    }
    else if (strAction.equals("MIN")) {
        outToClient.writeBytes("The max is: " + Integer.toString(numbers.first()));
    }
}

}

回答1:

Since you are using readLine(), I would guess that you actually need to send line terminators.



回答2:

My experience with TCP socket communications uses ASCII data exclusively, and my code reflects that I believe. If that's the case for you, you may want to try this:

First, try instantiating your data streams like this:

socket     = new Socket (Dest, Port);
toServer   = new PrintWriter (socket.getOutputStream(), true);
fromServer = new BufferedReader (new InputStreamReader
    (socket.getInputStream()), 8000);

The true at the end the printWriter constructor tells it to auto flush (lovely term) the buffer when you issue a println.

When you actually use the socket, use the following:

toServer.println (msg.trim());
resp = fromServer.readLine().trim();

I don't have to append the \n to the outgoing text myself, but this may be related to my specific situation (more on that below). The incoming data needs to have a \n at its end or readLine doesn't work. I assume there are ways you could read from the socket byte by byte, but also that the code would not be nearly so simple.

Unfortunately, the TCP server I'm communicating with is a C++ program so the way we ensure the \n is present in the incoming data isn't going to work for you (And may not be needed in the outgoing data).

Finally, if it helps, I built my code based on this web example:

http://content.gpwiki.org/index.php/Java:Tutorials:Simple_TCP_Networking

Edit: I found another code example that uses DataOutputStream... You may find it helpful, assuming you haven't already seen it.

http://systembash.com/content/a-simple-java-tcp-server-and-tcp-client/