简体   繁体   中英

Handling multi Java TCP clients with Threads

I have been working with TCP server/client stuff for a while. I am actully good at UDP programming when it comes to connecting more than one user that is multiple clients. I tried to do the same on a TCP server that i made using Threads but whenever the Thread gets to this piece of code

String reader = (String)in.readObject();

an error is generated and the thread stops executing the code but the thread still runs the program keeping it alive. Anyway here is the entire source code :

public class TestServer implements Runnable {

private Thread run, streams, connect, receive, send;

private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;

private boolean running, incomingMessage = false;
private int port;

public TestServer(int port) throws IOException {

    this.port = port;

    socket = new ServerSocket(port);

    console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);

    run = new Thread(this, "Run");
    run.start();

}

public void run() {

    running = true;
    connect();
    receive();
}

private void connect() {

    connect = new Thread("Connect") {

        public void run() {

            while(running) {

                try {
                    conn = socket.accept();
                } catch (IOException e) {

                    e.printStackTrace();
                }

                console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());

                try {
                    setupStreams();
                } catch (IOException e) {

                    e.printStackTrace();
                }

            }


        }

    }; connect.start();

}

private void setupStreams() throws IOException {

    streams = new Thread("Streams") {

        public void run() {

            try {

                console("Setting up Streams");

                out = new ObjectOutputStream(conn.getOutputStream());
                out.flush();

                in = new ObjectInputStream(conn.getInputStream());

                console("Streams are now setup");

                incomingMessage = true;
                receive.start();

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

    }; streams.start();



}

private void receive() {

    receive = new Thread("Receive") {

        public void run() {

            while(incomingMessage) {

                String message = "";

                try {

                    message = (String) in.readObject();
                    //This is the only flaw the program

                } catch (ClassNotFoundException | IOException e) {

                    e.printStackTrace();
                }

                console("Client : " + message);
            }
        }

    };
}

private void console(String message) {
    System.out.println(message);
}

public static void main(String[] args) {
    try {
        new TestServer(1234);
    } catch (IOException e) {

        e.printStackTrace();
    }
}

}

FYI am not new to this. The error is caused because the server starts receiving packets even when there are no packets to be received. But because the thread forces it to receive it, i generates the error in the thread and dont know any other way to counter this. So please help. Thanks in Advance.

You shouldn't need 2 threads per connection. One thread is all that's required. After the connection is accepted, pass it to a worker thread to start reading. This can be done in a while loop in the worker thread.

Even though the socket's input stream can be read, the ObjectInputStream() class is more sensitive. If there is any error, its state is corrupted and it can't be used.

    while (true) {
        try {
            Object input = in.readObject();
            message = (String) input;
        } catch (IOException e) {
            e.printStackTrace();
            break; //unrecoverable
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            break; //unrecoverable
        }

        console("Client : " + message);
    }

It's a better design to use a specific message protocol instead of sending serialized Java objects. For example if you are sending Strings like your sample, an InputStreamReader can be used to convert bytes to characters more easily and with less error handling.

These resources would be helpful to you:

https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later

Java - Listening to a socket with ObjectInputStream

ObjectInputStream(socket.getInputStream()); does not work

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM