Java - 服务器网络特定的客户端聊天

时间:2015-08-10 17:59:05

标签: java networking server chat

我创建了一个简单的聊天服务器,写入所有连接的客户端(为了简单起见,我只发布了核心代码)

public class server extends Thread {

private Socket clientSocket;
private static ArrayList<Socket> sockets = new ArrayList<Socket>();

public server(Socket clientSocket) {
    this.clientSocket = clientSocket;
    sockets.add(clientSocket);
}

public void run() {
    while (true) {
        try {
            for(Socket s: sockets) {
            //write something
            //the for loop will send it to every socket in the array
            }
        } catch (Exception e) {
            //catch it
        }   
    }    
}
}   

现在我想更具体地说明我想要发送消息的客户端,就像真实聊天应用程序将有不同的聊天室一样。

因此,如果Client1连接到服务器,他将要启动一个名为的聊天组 “苹果”。然后当Client2和Client3连接时,他们可以选择加入“Apple”组。同时,客户端4将连接到服务器并创建另一个名为“Banana”的聊天组,其他客户可以加入并在那里聊天。

我的理解是我需要以某种方式识别服务器接受的每个客户端(我不知道如何实现它)。然后根据他们的群聊名称以某种方式将它们全部放入自己的阵列中?

我一直在搜索过去一周的示例代码,这些代码允许同时进行多个群组聊天,但我看到的所有内容都只适用于1。

2 个答案:

答案 0 :(得分:1)

最简单的解决方案是使用带有key =房间名称的hashmap和值=聊天中的用户列表。在实践中:

HashMap<String, ArrayList<Socket>> rooms = new HashMap<>();

当新用户连接时,它会发送一条消息,其中包含他想要联合的房间的名称,之后您可以检查该房间是否已经存在:

ArrayList<Socket> clientsList = rooms.get(roomName);
if(clientsList == null) {
    clientsList = new ArrayList<Socket>();
    rooms.put(roomName, clientsList);
}
clientsList.add(socket);

另一个好主意可能是创建一个包含Socket的Client类以及其他信息(例如用户名)。

答案 1 :(得分:0)

对于性能方面,我建议你看一下Java nio,nio2。使用nio,您可以以异步方式处理连接,并且不会浪费每个连接1个线程。标准插座的插件有一些缺点。

作为您问题的解决方案,我更愿意分开发送/接收的邮件的标题和内容。在标题中将有源用户,目标用户/组等信息。 您的客户将理解并使用正确的发件人将消息打印到相关的聊天窗口中。

在服务器端,您可能有 用户映射哪个键是userName,值是User Object。 ChatGroups映射哪个键是groupName,值是用户名列表。 由于关系是多对多的,因此您需要保留用户的所有参与组。将groupNameList放在用户对象中或定义单独的地图。

侦听客户端套接字onClose操作(可能使用nio)并使用ablocking机制(并发)从组或映射中删除用户

同时添加新组,用户等也需要线程并发。