有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

网络Java聊天服务器

我正在编写一个基于java的聊天服务器,目前我的设计基于以下内容:- 当聊天室中的一个人发送消息时,服务器端的聊天室类将以循环的方式向聊天室中的每个参与者发送相同的消息。显然,这是一个糟糕的设计,因为网络呼叫是在循环中对单个参与者进行的。因此,例如,考虑有10人在聊天室。当一个用户发送消息时,聊天室类将以循环方式向所有10个人发送相同的消息。如果让我们说,循环中的第五个人有一个糟糕的连接,那么第六个人。。第10个人将看到消息将受到影响

如果我从单播移动到每个聊天室的多播,那么如何获得每个聊天室的私有多播组ip?而且,在每个聊天室里都有单独的群组似乎有些过分了。 其中一个主要问题是,当我通过一个循环在房间里回复用户时,通过socket连接发送数据的方法被阻塞了。因此,我在想,如果我使用非阻塞NIOsocket,然后以循环的方式将消息发送给收件人,这会解决问题吗? 有没有其他聪明的技巧可以用来优化向房间里的收件人发送数据


共 (3) 个答案

  1. # 1 楼答案

    简单的实现是每个客户端使用两个线程。一个线程从套接字读取,另一个线程向套接字写入。如果你几乎没有客户,这就可以了。你必须了解NIO才能处理许多客户。(“许多”表示线程模型无法正常工作。)

    客户端的读取线程从套接字读取整个消息,并将其放入聊天室对象的队列中。聊天室有一个线程,可以将消息从队列中删除,并将其放入客户端的队列中。客户端写入线程轮询其队列并将消息写入套接字

    聊天室有一个线程来接受连接,创建客户端对象,并将它们放入一个集合中。它有另一个线程来轮询其消息队列,并将消息分发到客户端队列

    Apache Mina有一个使用NIO的例子

  2. # 2 楼答案

    我同意连续循环你的收件人是个坏主意。为此,您可以考虑使用线程池来帮助。然而,我认为多播是你最好的选择。它非常适合聊天室模式。你只需要发送一次,你的迭代方法就会得到解决。通过在地址中指定不同的端口,可以获得唯一的组id

  3. # 3 楼答案

    简单的方法是每个客户端连接使用两个线程。一个线程负责从客户端读取消息,另一个线程负责发送消息,因此可以同时从客户端发送/接收消息

    为了避免在客户端连接上循环以广播消息时发生网络调用,服务器线程应该将消息添加到队列中以发送给客户端。java中的LinkedBlockingQueue。util。concurrent非常适合这样做。下面是一个例子:

    /**
     * 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);
            }
        }
    }