我的计划说明
我使用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 ArrayListuserList; //A list of users, where each user is a client connected to the server protected LinkedList 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 (10); this.chatRooms = new LinkedList (); 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.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 LinkedListchatRooms; 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
Chatroom.java
public class Chatroom { private String name; //Name of the chatroom protected LinkedListmessages; //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 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 (); 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; } }
小智.. 6
首先,没有调用
createUser()
哪个代码接受套接字连接.接下来是这个代码的
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
出存储的输入,在while循环内有另一个readUTF()
调用.
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(); }即使这不是最佳解决方案,因为每次都需要Server将某些内容写入流中.
另一个解决方案是使用不同的线程进行读写,这样我们就可以创建像聊天一样的全双工,这与半双工不同.
由于没有初始化
chatRooms
LinkedList,所以有一些NPE ,加上一些逻辑错误,例如,不将chatRooms添加到其List中.
错误的代码:
protected Chatroom createChatRoom(String roomName) { Chatroom room = new Chatroom(roomName); return room; }更正代码:
protected Chatroom createChatRoom(String roomName) { Chatroom room = new Chatroom(roomName); this.chatRooms.add(room); return room; }解决所有错误的最佳方法是Github和一些贡献者:p
1> 小智..:首先,没有调用
createUser()
哪个代码接受套接字连接.接下来是这个代码的
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
出存储的输入,在while循环内有另一个readUTF()
调用.
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(); }即使这不是最佳解决方案,因为每次都需要Server将某些内容写入流中.
另一个解决方案是使用不同的线程进行读写,这样我们就可以创建像聊天一样的全双工,这与半双工不同.
由于没有初始化
chatRooms
LinkedList,所以有一些NPE ,加上一些逻辑错误,例如,不将chatRooms添加到其List中.
错误的代码:
protected Chatroom createChatRoom(String roomName) { Chatroom room = new Chatroom(roomName); return room; }更正代码:
protected Chatroom createChatRoom(String roomName) { Chatroom room = new Chatroom(roomName); this.chatRooms.add(room); return room; }解决所有错误的最佳方法是Github和一些贡献者:p