在Java中为自定义聊天室创建Server类和Client类

时间:2018-10-08 23:47:49

标签: java multithreading server client-server chat

我的程序的说明

我使用Java创建了一个聊天室服务器,该服务器由3个类组成:服务器类,用户类和聊天室类。我还创建了一个客户端类以与服务器交互。每次客户端连接到服务器时,服务器都会创建一个用户对象。每个用户对象都会跟踪用户所在的聊天室,并运行一个线程来侦听用户输入。一个服务器对象遍历每个聊天室,以查看它是否在上周使用过。

问题

我想知道如何使用客户端对象实际连接到服务器。目前,我打开了两个eclipse实例。我在一个程序中运行服务器程序,在另一个程序中运行客户端程序,但是在任何一个程序的控制台中我什么都没收到,这是应该发生的,因为服务器应该向客户端发送信息,然后客户端将这些信息显示在控制台上。然后,客户端上的人员可以提供客户端将接受并发送到服务器的输入。

我想知道为什么现在什么都没发生,我能做些什么改进。


主文件


Server.java

/*
 * Creates a server that can host up to 10 clients who can join chat rooms, post messages in chatrooms, and view posts made by other clients within the same chat room
 */
public class Server implements Runnable{
    protected ArrayList<User> userList; //A list of users, where each user is a client connected to the server
    protected LinkedList<Chatroom> chatRooms;   //A list of chatrooms where each client can post messages in, where messages can be seen by all clients in the chatroom
    private ServerSocket serverSocket;  //The socket for the server

    /*
     * Constructor for the server class. Initializes the server attributes,
     */
    public Server() {
        this.userList = new ArrayList<User>(10);
        this.chatRooms = new LinkedList<Chatroom>();
        try {
            this.serverSocket = new ServerSocket(5000);
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * Creates a new user when a client connects to the server, and starts a user thread
     */
    public void createUser() {
        try {
            Socket userSocket = serverSocket.accept();
            Thread user = new Thread(new User(userSocket, this));
            user.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * Creates a chatroom for clients to interact in
     * @param roomName: The name of the chat room to be created
     */
    protected Chatroom createChatRoom(String roomName) {
        Chatroom room = new Chatroom(roomName);
        return room;
    }

    /*
     * Receives messages from clients and performs actions based on the requests of the client
     * (non-Javadoc)
     * @see java.lang.Thread#run()
     */
    public void run() {
        long currentTime;
        while(true) {
            try {
                currentTime = System.currentTimeMillis() / 1000;
                //Loop through each chatroom and check if the chatroom has been used(joined or had a message sent to it) and remove that chatroom if it hasn't been used in a week
                for (int i = 0; i < chatRooms.size(); i++) {
                    if (currentTime - 604800 >= chatRooms.get(i).dateLastUsed) {
                        chatRooms.remove(i);
                        //Also remove the chatroom from clients lists of chatrooms
                    }
                }

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

    public static void main(String args[]) {
        Server server = new Server ();
        server.run();
    }
}

Client.java

public class Client extends Thread{
    private String ip = "127.0.0.1";
    private int port = 5000 ;
    private Socket socket;
    private DataInputStream iStream;
    private DataOutputStream oStream;
    private String input;

    public Client() {
        try {
            this.socket = new Socket(ip, port);
            this.iStream = new DataInputStream(socket.getInputStream());
            this.oStream = new DataOutputStream(socket.getOutputStream());
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * Sends a message to the user
     * @param message: The message to be sent to the user
     */
    protected void send (String message) {
        try {
            oStream.writeUTF(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * Closes the connection to the client
     */
    protected void close () {
        try {
            iStream.close();
            oStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * Runs a thread for the client to constantly receive the clients input(non-Javadoc)
     * @see java.lang.Thread#run()
     */
    public void run() {
        try {
            Scanner reader = new Scanner(System.in);
            input = iStream.readUTF();
            String userInput;//Check if there is input from the user
            while (input != null) {
                input = iStream.readUTF();
                System.out.println(input);
                userInput = reader.next();
                oStream.writeUTF(userInput);
            }
            reader.close();
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        Client client = new Client();
        client.run();
    }

}

Server.java使用的对象


User.java

//Each user represents a client that has connected to the server
public class User implements Runnable{
    private DataInputStream inputStream;
    private DataOutputStream outputStream;
    private Socket socket;
    private String name;
    protected LinkedList<Chatroom> chatRooms;
    private String input;
    private Server server;

    /*
     * User Constructor, create a user for each client connecting to the server
     * @socket The socket that the user will be communicated through
     * The client is prompted to create a name for themself, they are they prompted to do an action.
     */
    public User(Socket socket, Server server) {
        this.socket = socket;
        this.server = server;
        try {
            inputStream = new DataInputStream(socket.getInputStream());
            outputStream = new DataOutputStream(socket.getOutputStream());
            outputStream.writeUTF("Enter a name");
            this.name = inputStream.readUTF();
            String message = "Create a chatroom: create \nList Chat Rooms: list \n Join Chat Room: join \n Leave Chat Room: Leave";
            send(message);
        } catch (IOException e) {   
        }
    }

    /*
     * Returns the current amount of chatrooms this user is in
     */
    protected int chatRoomLength () {
        return this.chatRooms.size();
    }

    /*
     * Gets the most recent input from the user
     */
    protected String getInput() {
        return input;
    }

    /*
     * Puts a user/client in a chatroom
     * @param cRoom: The chatroom that the user will join 
     */
    protected void joinRoom (Chatroom cRoom) {
        chatRooms.add(cRoom);
    }

    /*
     * Removes a user/client from a chatroom
     */
    protected void leaveRoom (Chatroom c) {
        chatRooms.removeFirstOccurrence(c);
    }

    /*
     * Sends a message to the user
     * @param message: The message to be sent to the user
     */
    protected void send (String message) {
        try {
            outputStream.writeUTF(message);
        } catch (IOException e) {
        }
    }

    /*
     * Closes the connection to the client
     */
    protected void close () {
        try {
            inputStream.close();
            outputStream.close();
            socket.close();
        } catch (IOException e) {}
    }

    /*
     * Runs a thread for the client to constantly receive the clients input(non-Javadoc)
     * @see java.lang.Thread#run()
     */
    public void run() {
        try {
            input = inputStream.readUTF();  //Check if there is input from the user
            //if the user has disconnected from the server, remove them from the list
            if (input == null) {
                this.close();
                this.server.userList.remove(this);
            }else if (input.equals("create")){  //create a chat room
                this.send("Name the Chatroom");
                input = this.getInput();
                Chatroom c = this.server.createChatRoom(input);
                this.joinRoom(c);
            }else if (input.equals("list")) {   //List the current chatrooms
                String rooms = "";
                for (int j = 0; j< server.chatRooms.size(); j++) {
                    rooms = rooms + server.chatRooms.get(j).getName() + "\n";
                }
                this.send(rooms);
            }else if (input.equals("join")) {   //Join the user to a chat room
                int end = chatRooms.size();
                if (end == 0) {
                    this.send("There's currently no chat rooms");
                }else { 
                    this.send("Which room would you like to join");
                    input = this.getInput();
                    for (int k = 0; k < end; k++) {
                        if (chatRooms.get(k).getName().equals(input)) {
                            Chatroom joinRoom = chatRooms.get(k);
                            this.joinRoom(joinRoom);
                            String message = "Chatroom " + input + " messages. \n";
                            //Print the current messages in the chatroom to the user
                            for (int j = 0; j < joinRoom.messages.size(); j++ ) {
                                message = message + joinRoom.messages.get(j) + "\n";
                            }
                            this.send(message);
                        } else if (k == end - 1) {
                            this.send("There's no chat rooms by that name");
                        }
                    }
                }
            }else if (input.equals("leave")) {  //Remove the user from a chatroom
                int end = this.chatRoomLength();    //if the chatroom list of the user is empty
                if (end == 0) {
                    this.send("You are not in any Chat Rooms");
                }else {
                    this.send("Which room would you like to leave");
                    input = this.getInput();

                    for (int m = 0; m < end; m++) { //find the chatroom by the same name
                        if (this.chatRooms.get(m).getName().equals(input)) {
                            this.chatRooms.remove(m);
                            this.send("Great! You've been removed from" + input);
                        } else if (m == end - 1) {
                            this.send("You're not in a chatroom named" + input);
                        }
                    }
                }
            }else { //All other input is interpreted as a message to be posted in the chatrooms that the user is in
                int end = this.chatRoomLength();
                if (end == 0) {
                    this.send("You can't write to any chat rooms because you are not in any");
                }
                for (int m = 0; m < end; m++) { //Add the users message to ALL the chatrooms the user is in
                    Chatroom c = this.chatRooms.get(m);
                    c.addMessage(input);
                    //Send this added message to all the users in this chatroom
                    for (int n = 0; n < c.users.size(); n++) {
                        User u = c.users.get(n);
                        u.send("Chatroom" + c.getName() + ":" + input);
                    }
                }
            }

        }catch (IOException e) {
        }
    }
}

Chatroom.java

public class Chatroom {
    private String name;        //Name of the chatroom
    protected LinkedList<String> messages;  //List of text messages that have been sent by users to the chatroom and are displayed in the chatroom
    protected long dateLastUsed;        //The last time the chatroom was joined or had a message sent to it
    protected LinkedList<User> users;   //The clients/users that are currently in the chatroom

    /*
     * Chatroom constructor
     * @param name The name of the chatroom, as determined by the user creating it
     */
    public Chatroom(String name) {
        dateLastUsed = System.currentTimeMillis() / 1000;       //Sent the time that the chatroom was used last to the current UNIX Epoch time
        messages = new LinkedList<String>();
        this.name = name;
    }

    /* 
     * Adds a message into the chatroom
     * @param message The message to be added to the chatroom
     */
    protected void addMessage(String message) {
        messages.add(message);
        dateLastUsed = System.currentTimeMillis() / 1000;
    }

    /*
     * Returns the name of the chatroom
     * @return String equal to the name of the chatroom
     */
    protected String getName() {
        return this.name;
    }

}

1 个答案:

答案 0 :(得分:6)

首先,没有对run()的调用,该调用具有接受套接字连接的代码。

接下来是try { Scanner reader = new Scanner(System.in); input = iStream.readUTF(); String userInput;//Check if there is input from the user while (input != null) { input = iStream.readUTF(); System.out.println(input); userInput = reader.next(); oStream.writeUTF(userInput); } 函数中的这段代码,

Enter a name

接受套接字后,服务器将打印存储的输入readUTF(), 在while循环内,还有另一个readUTF()调用。

writeUTF()调用的问题在于它被阻塞,即。如果没有来自服务器的try { Scanner reader = new Scanner(System.in); String userInput;//Check if there is input from the user do { input = iStream.readUTF(); System.out.println(input); userInput = reader.next(); oStream.writeUTF(userInput); } while (input != null); reader.close(); } 调用,它将等待数据。

我通过以下代码段解决了这个问题,

chatRooms

即使这也不是最佳解决方案,因为它需要Server每次都将一些内容写入流中。

另一种解决方案是使用不同的线程进行读取和写入,这样我们就可以像聊天一样创建全双工,而不是半双工。

然后由于未初始化protected Chatroom createChatRoom(String roomName) { Chatroom room = new Chatroom(roomName); return room; } LinkedList而有一些NPE,

加上一些逻辑错误,例如不将chatRooms添加到其列表中。

错误代码:

protected Chatroom createChatRoom(String roomName) {
        Chatroom room = new Chatroom(roomName);
        this.chatRooms.add(room);
        return room;
    } 

更正的代码:

JTextArea

解决所有错误的最好方法是Github和一些贡献者:p