繁体   English   中英

Java中的多线程客户端服务器聊天应用程序

[英]Multithreaded client server chat application in java

我正在尝试用Java编写多线程客户端服务器聊天应用程序。 我只想创建两个线程,从每个线程发送一些数字,然后从服务器获取相同的数字。 但是出了点问题。 客户端仅从一个线程发送数字,而服务器不返回所有数字

这是客户代码

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);
        }
    }

}

和服务器代码

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);
        }
    }

}

每个新客户端都应位于服务器端的单独Thread上,您要为serviceSocket分配一个new Socket ,这样您就基本上会忽略以前连接的客户端。

您启动一个new Server而不是为刚刚连接的客户端启动一个Thread 您应该为每个连接的客户端创建一个new Socket ,并在连接客户端后在不启动new Servernew Thread上运行它。

UPDATE

这是基本的多客户端服务器的示例:

服务器代码由几个类组成:

// 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();
    }

}

和客户端示例:

// 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();
        }

    }

}

这不是最好的例子,但我希望您可以使用它并根据需要进行调整。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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