现在,我已经完成了具有服务器和客户端的应用程序,服务器接受了客户端请求并将客户端对象添加到Arraylist中,并为每个客户端启动了一个新线程。当多个客户端连接时,客户端可以列出所有客户端,并且可以向列表中的任何客户端发送消息。例如client1,client2,client3连接到服务器client1,而client2发送消息到client3,它将在client3控制台中打印。一切正常。现在,我需要添加其他功能,即每个客户端在单独的聊天中发送消息,如果client1与client2打开聊天,则仅应显示这两个客户端之间的对话,而不是client3消息,反之亦然。为此,我需要任何其他概念,例如多线程。我不是在问源代码,我只是在问实现上述功能的想法。
任何人都可以告诉我有关为不同客户端实施单独聊天的建议或参考...需要保留旧消息直到服务器脱机吗?
Server.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();
}
}
}
ClientHandler.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());
}
}
}
Client.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();
}
}
如果我的代码中有不相关的语句,请提出一种优化代码的更好方法
答案 0 :(得分:1)
第一个答案是:是的,可能。
第二个答案:这与线程无关,您必须首先考虑(这很重要,但不要放在首位)。
第三个答案:据我了解您的代码,主要的数据结构是客户端及其处理程序的集合。我认为在两者之间还缺少另一个抽象层。 首先,考虑一下“ chatRoom”之类的数据结构。连接到服务器的客户端必须向服务器发送“ chatRoom”名称。比服务器创建chatRoom或将客户端添加到chatRooom的客户端集中。从那时起,客户端可以将其消息发送到chatRoom,而不再直接发送给客户端。 进一步的步骤:要启用向单个客户端发送消息的功能,您可以为每对客户端强制执行一个chatRoom(请注意:这可能会非常广泛),因此客户端之间仍然可以进行单独的通信。