我正在编写一个基于java的聊天服务器,目前我的设计基于以下内容:-当聊天室中的人发送消息时,服务器端的聊天室类在循环中向房间中的每个参与者发送相同的消息。显然,这是一个糟糕的设计,因为网络呼叫是在循环中向单个参与者发出的。因此,例如,假设聊天室中有10个人。当一个用户发送消息时,聊天室类将循环发送相同的消息给所有10个人。假如说,循环中的第五个人有一个糟糕的连接,当第六个人..第10个人将看到该消息将受到影响。
如果我从每个聊天室的单播转移到多播,那么我如何获得每个聊天室的私有多播组ip?此外,每个聊天室都有单独的群组似乎有些夸张。其中一个主要问题是,当我在房间里通过循环回复用户时,通过套接字连接发送数据的方法是阻塞的。因此,我在想,如果我使用非阻塞NIO套接字,然后在循环中将消息发送给收件人,这会解决问题吗?是否有其他聪明的技巧可以优化向房间中的收件人发送数据?
发布于 2009-07-20 04:51:02
简单的实现是每个客户端使用两个线程。一个线程从套接字读取,另一个线程写入套接字。如果你有很少的客户,这将是很好的。您必须了解NIO才能处理许多客户端。(“许多”是指线程模型不能很好地工作。)
客户端的读取线程从套接字读取整个消息,并将其放入ChatRoom对象的队列中。聊天室有一个线程,它将消息从队列中移出,并将它们放入客户端的队列中。编写线程的客户端轮询其队列,并将消息写入套接字。
ChatRoom有一个线程,用于接受连接、创建客户端对象并将它们放入集合中。它有另一个线程来轮询其消息队列,并将消息分发到客户端队列。
Apache Mina有一个使用NIO的示例
发布于 2009-07-20 04:51:23
我同意连续循环遍历收件人不是一个好主意。为此,您可以考虑使用ThreadPool来提供帮助。然而,我认为多播将是您最好的选择。它非常适合聊天室模型。你只需要发送一次,你的迭代方法就会解决。您可以通过在地址中指定不同的端口来获取唯一的组id。
发布于 2009-07-20 05:41:03
简单的方法是为每个客户端连接使用两个线程。一个线程负责从客户端读取消息,另一个线程负责发送消息,从而可以同时从客户端发送/接收消息。
为避免在循环客户端连接以广播消息时进行网络调用,服务器线程应将消息添加到队列中以发送到客户端。java.util.concurrent中的LinkedBlockingQueue非常适合这一点。下面是一个示例:
/**
* Handles outgoing communication with client
*/
public class ClientConnection extends Thread {
private Queue<String> outgoingMessages = new LinkedBlockingQueue<String>(MAX_OUTGOING);
// ...
public void queueOutgoing(String message) {
if (!outgoingMessages.offer(message)) {
// Kick slow clients
kick();
}
}
public void run() {
// ...
while (isConnected) {
List<String> messages = new LinkedList<String>();
outgoingMessages.drainTo(messages);
for (String message : messages) {
send(message);
}
// ...
}
}
}
public class Server {
// ...
public void broadcast(String message) {
for (ClientConnection client : clients) {
client.queueOutgoing(message);
}
}
}https://stackoverflow.com/questions/1151652
复制相似问题