- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我的程序说明
我使用 Java 创建了一个聊天室服务器,它由 3 个类组成:服务器类、用户类和聊天室类。我还创建了一个客户端类来与服务器交互。每次客户端连接到服务器时,服务器都会创建一个用户对象。每个用户对象都跟踪用户所在的聊天室,并运行一个线程来监听用户输入。服务器对象循环遍历每个聊天室,看看它是否在上周被使用过。
问题
我想知道如何使用客户端对象实际连接到我的服务器。目前我打开了两个 Eclipse 实例。我在一个服务器程序中运行我的服务器程序,在另一个程序中运行我的客户端程序,但是我在任何一个控制台中都没有收到任何东西,这应该发生,因为服务器应该向客户端发送信息,然后客户端将在控制台上显示这些信息。客户端的人员然后可以提供客户端将接收并发送到服务器的输入。
我想知道为什么现在什么都没有发生,以及我可以做出哪些改进。
主要文件
服务器.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();
}
}
客户端.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 使用的对象
用户.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) {
}
}
}
聊天室.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;
}
}
最佳答案
首先,没有调用 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();
}
即使这也不是最佳解决方案,因为它需要服务器每次都向流中写入一些内容。
另一种解决方案是使用不同的线程进行读取和写入,这样我们就能够创建像聊天这样的全双工,而不像这种半双工。
然后由于chatRooms
LinkedList没有初始化,出现了一些NPE,
加上一些逻辑错误,比如没有将 chatRooms 添加到它的列表中。
错误代码:
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
关于java - 在 Java 中为自定义聊天室创建服务器类和客户端类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52711481/
我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我的第一个想法如下: 我在服务器上创建了一个中央 ServerSocket,所有应用程序都可以连接到该服务器。
我正在 Unity 中构建多人游戏。为此,我必须将一些值从客户端发送到两个或多个通过服务器连接的客户端。我想将其构建为服务器真实游戏。客户端将使用 Android,他们的数据将通过服务器同步(可能是一
练习 C 网络编程:我正在编写一个简单的 TCP 客户端-服务器应用程序,它应该将消息(在每个客户端的单独线程中)作为字符串从服务器发送到客户端并在客户端(稍后将成为控制台商店应用程序)。我首先发送消
我使用证书身份验证设置了 AWS Client VPN。我正在为客户端-客户端访问系统进行设置,基本上如 this AWS scenario/example 中所述.一切正常,如果我知道他们的 IP
我正在开发一个小型客户端1/客户端2、服务器(线程)TCP 游戏。在尝试处理延迟问题时,我意识到我的 transmitState() 中存在缺陷。它强制将不必要的信息传递到通讯流中,从而造成迟缓,将汽
来自文档:Configurable token lifetimes in Azure Active Directory (Public Preview) 它提到“ secret 客户端”,刷新 tok
Apollo 客户端开发工具无法连接到我的应用程序。我已在 ApolloClient 构造函数中将 connectToDevTools 传递为 true,但没有任何 react 。我也试过this p
我想在 Pod 内使用 Fabric8 kubernetes 客户端 (java)。如何获取部署集群的 kubernetes 客户端? 我可以使用该集群的 kubeconfig 文件获取任何集群的配置
我正在阅读 the security issue with Log4j我了解此产品受此漏洞影响。但是 Oracle 客户端 11.2 和 12 是否受此问题影响? 我找不到这些产品是否使用任何 Log
Eureka 服务器设置 pom.xml 1.8 Hoxton.SR1 org.springframework.cloud spring
我有一个点对点(客户端/服务器)设置(通过本地 LAN),它使用 Netty,一个 Java 网络框架。我使用原始 TCP/IP(例如,没有 HTTP)进行通信和传输。现在,根据要求,我们希望转向 T
上一篇已经实现了ModbusTcp服务器和8个主要的功能码,只是还没有实现错误处理功能。 但是在测试客户端时却发现了上一篇的一个错误,那就是写数据成功,服务器不需要响应。 接下来要做的就是实现Modb
有没有办法将二维十六进制代码数组转换为 png 图像? 数组看起来像这样(只是更大) [ [ '#FF0000', '#00FF00' ], [ '#0000FF'
我是套接字编程的新手。每次我运行客户端程序时,它都会说“无法连接到服务器”。谁能告诉我我在哪里犯了错误。任何帮助将不胜感激。 这是client.c #include #include #inclu
我们在UNIX环境下制作了简单的client.c和server.c程序。我们使用它来传输一个简单的文本文件,首先打开它,然后读取它并使用 open、read 和 send 系统调用发送;在客户端,我接
当我的程序来自 my previous question正在响应客户端,它应该发送加密消息。 当客户端连接时,它会发送一条类似“YourMessage”的消息。现在我想做的是,当客户端连接时,应该以某
我正在使用 C 和 putty 编写客户端/服务器程序。两个 c 文件位于同一系统上。 我目前在向客户端写回其正在使用的框架以及打印我的框架时遇到问题。它打印出 3 0 9 8,但随后开始打印 134
我正在使用 C 中的 select() 制作一个模拟快餐或其他任何东西的客户端服务器。 我有客户随机点 1-5 种“食物”。服务器每 30 秒决定一次。所有客户最喜欢的食物是什么?他为那些客户提供服务
对于单机游戏,基本的游戏循环是(来源:维基百科) while( user doesn't exit ) check for user input run AI move enemies
1、CentOS安装TortoiseSVN 复制代码 代码如下: yum install -y subversion 2、SVN客户端命令
我是一名优秀的程序员,十分优秀!