java - 在 java 套接字编程聊天应用程序中,是否可以像 whatsapp 一样为每个客户端创建单独的聊天?
问题描述
现在我完成了具有服务器和客户端的应用程序,服务器接受客户端请求并将客户端对象添加到 Arraylist 并为每个客户端启动一个新线程。当多个客户端连接时,客户端可以列出所有客户端,并且可以向列表中的任何客户端发送消息。例如client1,client2,client3连接到服务器client1,client2向client3发送消息,会在client3控制台打印。一切正常。现在我需要添加每个客户端在单独聊天中发送消息的附加功能,如果客户端 1 打开与客户端 2 的聊天,则应该只显示这两个客户端之间的对话,而不是客户端 3 消息,反之亦然。要做到这一点,我需要任何额外的概念,比如多线程。我不是在问源代码,我'
谁能告诉我为不同客户实施单独聊天的建议或参考...需要保留旧消息直到服务器离线?
服务器.java
package server;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.*;
import java.util.Vector;
public class Server {
static Vector<ClientHandler> AllClients = new Vector<ClientHandler>();
public static void main(String args[]) throws Exception {
try {
ServerSocket ss = new ServerSocket(1111);
System.out.println("Server Started");
while(true) {
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
String clientname = dis.readUTF();
System.out.println("Connected With : "+clientname);
ClientHandler client = new ClientHandler(s,clientname);
Thread t = new Thread(client);
AllClients.add(client);
t.start();
System.out.println("Ready to accept connections...");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端处理程序.java
package server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;
public class ClientHandler extends Thread{
private DataInputStream in;
private DataOutputStream out;
private String ClientName;
private boolean login;
private Socket Socket;
Scanner sc = new Scanner(System.in);
ClientHandler(Socket s,String name) throws Exception{
this.in = new DataInputStream(s.getInputStream());
this.out = new DataOutputStream(s.getOutputStream());
this.login = true;
this.ClientName = name;
this.Socket = s;
}
public void run() {
while(true) {
try {
String received = in.readUTF();
if(received.equalsIgnoreCase("logout")) {
this.login = false;
this.out.writeUTF("logout");
int i;
for(i = 0; i < Server.AllClients.size(); i++) {
if(this.ClientName.equals(Server.AllClients.get(i).ClientName))
break;
}
Server.AllClients.remove(i);
System.out.println(this.ClientName+" logged out");
this.Socket.close();
break;
}
if(received.equalsIgnoreCase("getlist")) {
for(int i = 0; i < Server.AllClients.size(); i++) {
out.writeUTF(i+1 +", "+Server.AllClients.get(i).ClientName);
}
continue;
}
if(received.contains(",")) {
String[] Message = received.split(",");
for(ClientHandler c : Server.AllClients) {
if(c.ClientName.equalsIgnoreCase(Message[1]) && c.login) {
c.out.writeUTF(this.ClientName +" : "+ Message[0]);
c.out.flush();
break;
}
}
}
}catch(Exception e) {
System.out.println("Error :"+e.getMessage());
}
}
try {
this.in.close();
this.out.close();
}catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
客户端.java
package client;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
static DataInputStream dis;
static DataOutputStream dos;
static Socket s;
public static void main(String args[])throws Exception {
Scanner sc = new Scanner(System.in);
System.out.println("Enter Cient Name : ");
String name = sc.nextLine();
s = new Socket("localhost",1111);
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(name);
Thread sendMessage = new Thread(new Runnable()
{
@Override
public void run() {
while (true) {
String msg = sc.nextLine();
try {
dos.writeUTF(msg);
if(msg.equalsIgnoreCase("logout")) {
System.out.println("Logged out");
break;
}
} catch (IOException e) {
System.out.println("Error in send method :"+e.toString());
}
}
}
});
Thread readMessage = new Thread(new Runnable()
{
@Override
public void run() {
while (true) {
try {
String msg = dis.readUTF();
if(msg.equalsIgnoreCase("logout")) {
System.out.println("Logged out");
break;
}
System.out.println(msg);
} catch (IOException e) {
System.out.println("Error in read method :"+e.getMessage());
}
}
}
});
sendMessage.start();
readMessage.start();
}
}
如果我的代码有任何不相关的陈述,请建议一种更好的方法来优化代码
解决方案
第一个答案是:是的,这是可能的。
第二个答案:这与线程无关,您必须首先考虑(这很重要,但不是首先)。
第三个答案:据我了解,主要数据结构是客户端及其处理程序的集合。在我看来,中间还缺少一个抽象层。首先考虑像“chatRoom”这样的数据结构。连接到服务器的客户端必须向服务器发送一个“chatRoom”名称。然后服务器创建聊天室或将客户端添加到聊天室的客户端集。从那时起,客户可以将他的消息发送到聊天室,而不是直接发送给客户。在进一步的步骤中:为了能够向单个客户端发送消息,您可以例如为每对客户端强制一个聊天室(注意:这可能非常广泛),因此客户端之间的单独通信仍然是可能的。
推荐阅读
- android - 如何在 webView 中使用私有 url?
- ios - 使用 UNLocationNotificationTrigger
- mysql - Mariadb 服务器启动失败(code=killed)
- xcode - Xcodebuild:找不到与提供的目标说明符匹配的目标
- c++ - C++ 内核的 Jupyter 笔记本错误 [cling]
- powershell - 为什么 powershell 正则表达式不能与 \n 一起使用?
- android - 如何将类实例作为参数提供给 Kotlin 函数
- c++ - 您如何编码将不同的可执行文件合并到一个窗口框架中?像浏览器一样?
- python - 熊猫将数据框与条件合并
- html - 如何使用 react-native-render-html 从包含电话号码或电子邮件的 html 内容中单击打开电话应用程序或电子邮件?