在Java套接字编程聊天应用程序中,是否可以为每个客户端(如whatsapp)创建单独的聊天室?

时间:2019-11-26 06:43:10

标签: java sockets tcp client-server serversocket

现在,我已经完成了具有服务器和客户端的应用程序,服务器接受了客户端请求并将客户端对象添加到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(); 


    }


}



如果我的代码中有不相关的语句,请提出一种优化代码的更好方法

1 个答案:

答案 0 :(得分:1)

第一个答案是:是的,可能。

第二个答案:这与线程无关,您必须首先考虑(这很重要,但不要放在首位)。

第三个答案:据我了解您的代码,主要的数据结构是客户端及其处理程序的集合。我认为在两者之间还缺少另一个抽象层。 首先,考虑一下“ chatRoom”之类的数据结构。连接到服务器的客户端必须向服务器发送“ chatRoom”名称。比服务器创建chatRoom或将客户端添加到chatRooom的客户端集中。从那时起,客户端可以将其消息发送到chatRoom,而不再直接发送给客户端。 进一步的步骤:要启用向单个客户端发送消息的功能,您可以为每对客户端强制执行一个chatRoom(请注意:这可能会非常广泛),因此客户端之间仍然可以进行单独的通信。