简体   繁体   中英

Multithreaded client server chat application in java

I'm trying to write multithreaded client server chat application in java. I just want to create two threads, send from every thread some numbers, and get the same numbers from server. But something is going wrong. Client sends numbers just from one thread and Server returns not all numbers

Here is client code

import java.io.*;
import java.net.*;

public class Client implements Runnable{

    private Socket clientSocket = null;
    private DataInputStream input = null;
    private PrintStream output = null;
    private DataInputStream inputLine = null;
    private int id;

    public Client(int id){
        this.id = id;
    }

    public static void main(String[] args) throws IOException, InterruptedException {

        System.out.println("The client started. Type any text. To quit it type 'Ok'.");

        Client a = new Client(1);
        Thread one = new Thread(a);

        Client b = new Client(2);
        Thread two = new Thread(b);
        one.start();
        two.start();  

        one.join();
        two.join();               

    }

    public void run() {
        System.out.println("hi from thread" + id);
        try {
            clientSocket = new Socket("localhost", 4444);
            output = new PrintStream(clientSocket.getOutputStream());
            input = new DataInputStream(clientSocket.getInputStream());
            inputLine = new DataInputStream(new BufferedInputStream(System.in));
        } 
        catch( IOException e){
            System.out.println(e);
        }
        String responseLine;
        try{      
            for(int i = 0; i < 10; i++){
                output.println( id + " " + i);
                System.out.println("sended:" + id + " " + i);
                responseLine = input.readLine();
                System.out.println("received: " + responseLine);
            }
        }
        catch (IOException e) {
            System.out.println(e);
        }
    }

}

And server code

import java.io.*;
import java.net.*;

public class Server implements Runnable{
    private static ServerSocket MyService = null;        
    private  DataInputStream input = null;
    private  PrintStream  output = null;
    private  String line;
    private static Socket serviceSocket = null;

    public static void main(String[] args) throws IOException {


        try{
            MyService = new ServerSocket(4444);
            if(args.length > 0){
                MyService = new ServerSocket(Integer.parseInt(args[0]));
            }
        } 
        catch( IOException e){
            System.out.println("Couldn't linputten to port " + (args.length > 0 ? Integer.parseInt(args[0]) : 4444));
        }

        System.out.println("The server started. To stop it press <CTRL><C>.");
        while(true){
            try {
                serviceSocket = MyService.accept();            
                new Thread(new Server()).start(); 
                System.out.println("CREATED");
            }
            catch (IOException e) {
                System.out.println("can't accept");
            }
        }

    }

    public void run(){
        try {    
            input = new DataInputStream(serviceSocket.getInputStream());
            output = new PrintStream(serviceSocket.getOutputStream());
            while (true) {
                line = input.readLine();
                System.out.println("from client:" + line+"\n");
                output.println("From server: " + line+"\n");

            }

        }
        catch(IOException e) {
            System.out.println(e);
        }
    }

}

Every new client should be on seperate Thread on server side, you are assigning a new Socket to your serviceSocket and by that you basically ignore previously connected clients.

You start a new Server instead of starting a Thread for the client that just connected. You should create a new Socket for every client that is connected and run it on a new Thread not start a new Server after a client was connected.

UPDATE

Here is an example of a basic multiple client server:

The server code consists of a few classes:

// Server.java
public class Server {

    private ServerSocket        socket;
    private ConnectionListener  connectionListener;

    // temp
    private List<Client> clientList = new ArrayList<Client>();
    // temp end

    public Server(int port) {
        try {
            socket = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
        }

        connectionListener = new ConnectionListener(this);
    }

    public void start() throws IOException {

        connectionListener.start();

        // temp will move to a Thread later
        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
        String input;
        while (((input = stdIn.readLine()) != null) && connectionListener.isAlive()) {
            if (input.equalsIgnoreCase("exit")) {
                break;
            } else {
                for (int i = 0; i < input.length(); i++)
                    System.out.print("\b");
                System.out.println("Admin: " + input);
                for (Client c : clientList) {
                    c.send("Admin: " + input);
                }
            }

        }
        stop();
        // temp end
    }

    public void stop() {

        connectionListener.stop();
        for (Client c : clientList) {
            c.closeSession();
        }

        System.out.println("Server terminated!");
    }

    public synchronized void addConnection(Connection connection) {

        Client c = new Client(connection, clientList);
        clientList.add(c);
        c.startSession();
        System.out.println("Client connected");
    }

    public ServerSocket getSocket() {

        return socket;
    }

    public static void main(String[] args) throws IOException {

        int port;
        if (args.length > 0)
            port = Integer.parseInt(args[0]);
        else
            port = 4444;
        Server s = new Server(port);
        s.start();
    }

}

// ConnectionListener.java
public class ConnectionListener implements Runnable {

    private Server          server;
    private ServerSocket    socket;
    private boolean         running;
    private Thread          t;

    public ConnectionListener(Server server) {
        this.server = server;
        this.socket = server.getSocket();
        running = false;
    }

    public synchronized void start() {

        if (running)
            return;

        running = true;
        t = new Thread(this);
        t.start();
    }

    public synchronized void stop() {

        if (!running)
            return;

        System.out.print("Terminating connection listener on:" + socket.getLocalSocketAddress() + "...");

        running = false;

        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("TERMINATED!");
    }

    @Override
    public void run() {

        System.out.println("Listening for connections on: " + socket.getLocalSocketAddress());

        try {
            while (running) {
                Socket request = socket.accept();
                Connection connection = new Connection(request);
                server.addConnection(connection);
            }
        } catch (IOException e) {
            //e.printStackTrace();
        }

    }

    public boolean isAlive() {

        return running;
    }

}

// Connection.java
public class Connection {

    private Socket          socket;
    private BufferedReader  in;
    private BufferedWriter  out;
    private boolean         alive;

    public Connection(Socket socket) {
        this.socket = socket;
        try {
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        alive = true;
    }

    public String read() {

        try {
            if (in.ready()) {
                return in.readLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public void write(String data) {

        try {
            out.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void flush() {

        try {
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean close() {

        boolean result = true;
        try {
            in.close();
            out.close();
            socket.close();
            alive = false;
        } catch (IOException e) {
            e.printStackTrace();
            result = false;
        }
        return result;
    }

    public boolean isAlive() {

        return alive;
    }

}

// Client.java

/*
 * This is still server side, that is the handler for the connected clients
 */
public class Client implements Runnable {

    public static final long IDLE_TIME = 10;

    private Connection  connection;
    private boolean     alive;
    private Thread      t;

    private List<Client> clientList;

    public Client(Connection connection, List<Client> clientList) {
        this.connection = connection;
        this.clientList = clientList;
        alive = false;
    }

    public synchronized void startSession() {

        if (alive)
            return;

        alive = true;

        t = new Thread(this);
        t.start();

    }

    public synchronized void closeSession() {

        if (!alive)
            return;

        alive = false;

        try {
            connection.close();
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void run() {

        while (connection.isAlive()) {

            String in = connection.read();
            if (in != null) {
                System.out.println(in);
                for (Client c : clientList) {
                    c.send(in);
                }
            } else {
                try {
                    Thread.sleep(IDLE_TIME);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }

    }

    public void send(String msg) {

        connection.write(msg + "\n");
        connection.flush();
    }

}

And the Client example:

// Client.java
public class Client {

    public static void main(String[] args) {

        String host;
        if (args.length > 0)
            host = args[0];
        else
            host = "localhost";

        int port;
        if (args.length > 1)
            port = Integer.parseInt(args[1]);
        else
            port = 4444;

        try (Socket socket = new Socket(host, port);
                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {

            Thread input = new Thread(() -> {
                String msg;
                try {
                    while ((msg = in.readLine()) != null) {
                        System.out.println(msg);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            input.start();

            String userName = "User" + ((int) (Math.random() * 200));
            String msg;
            try {
                while ((msg = stdIn.readLine()) != null) {
                    for (int i = 0; i < msg.length(); i++)
                        System.out.print("\b");
                    out.write(userName + ": " + msg + "\n");
                    out.flush();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

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

    }

}

It's not the best example but I hope you can work with it and tweak it to your needs.

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