Java聊天服务器

发布于 2024-07-27 20:55:29 字数 446 浏览 6 评论 0原文

我正在编写一个基于 java 的聊天服务器,目前我的设计基于以下内容:- 当聊天室中的一个人发送消息时,服务器端的聊天室类会循环发送相同的消息给房间中的每个参与者。 显然,这是一个糟糕的设计,因为网络调用是在循环中对各个参与者进行的。 因此,举例来说,假设聊天室中有 10 个人。 当一个用户发送一条消息时,聊天室类将循环发送相同的消息给所有 10 个人。 如果可以说,循环中的第五个人的连接很差,那么第六个人..第十个人看到该消息的时间就会受到影响。

如果我从每个房间的单播转移到多播,那么我如何获得每个聊天室的私有多播组 IP? 此外,每个聊天室都有单独的组似乎有些过分了。 主要问题之一是,当我通过循环回复房间中的用户时,通过套接字连接发送数据的方法被阻塞。 因此,我在想如果我使用非阻塞 NIO 套接字,然后循环发送消息给收件人,是否可以解决问题? 是否还有其他巧妙的技巧可以优化向房间内的收件人发送数据?

I am writing a java based chat server and currently my design is based on following :-
when a person in a chat room sends a message, the chatroom class at the server side, sends the same message to every participant in the room in a loop. Obviously , this is a poor design because networks calls are being made to individual participants in a loop. Hence, for example, consider there are 10 people in a chat room. When one user sends a message, the chatroom class will send the same message in a loop to all 10 people. if lets say, the 5th person in a loop has a crappy connection, the time when the sixth .. 10th person will see the message will be affected.

if i move from unicast to multicast per room, then how do i get a private multicast group ip per chat room? Also, it seems overkill to have individual groups per chat room.
One of the main problem is that when i replied to users in a room via a loop, the method that sent data over socket connection was blocking. Hence, i am thinking if i use non blocking NIO sockets, and then send the message to recipients in a loop, would that solve the problem ?
Are there other clever tricks that can be done to optimize sending of data to recipients in the room?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

记忆消瘦 2024-08-03 20:55:29

简单的实现是每个客户端使用两个线程。 一个线程从套接字读取数据,另一个线程向套接字写入数据。 如果你的客户很少,那就没问题了。 你必须了解蔚来才能处理许多客户。 (“很多”意味着线程模型不能很好地工作。)

客户端的读取线程从套接字读取整个消息并将其放入 ChatRoom 对象的队列中。 聊天室有一个线程从队列中取出消息并将它们放入客户端的队列中。 客户端写入线程轮询其队列并将消息写入套接字。

ChatRoom 有一个线程来接受连接并创建 Client 对象并将它们放入 Collection 中。 它有另一个线程来轮询其消息队列并将消息分发到客户端队列。

Apache Mina 有一个使用 NIO 的示例

The simple implementation is to use two threads per client. One thread to read from the socket the other to write to the socket. If you have few clients this will be fine. You will have to get to know NIO to handle many of clients. ('many' meaning when the threaded model does not work well.)

The Client's reading thread reads an entire message from the socket and puts it on a queue in the ChatRoom object. The chat room has a thread that takes messages off the queue and puts them on the Client's queue. The clients writing thread polls its queue and writes the message to the socket.

The ChatRoom has a thread to accept connections and create Client objects and puts them in a Collection. It has another thread to poll its message queue and distribute the messages to the Client queues.

Apache Mina has an example using NIO

眼藏柔 2024-08-03 20:55:29

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

I agree that serially looping over your recipients would be a bad idea. For this, you could consider using a ThreadPool to help. However, I would think that Multicast would be your best bet. It is well suited to the chatroom model. You would only need to send once and your iterative approach will be solved. You can get a unique group id by specifying a different port in your address.

咋地 2024-08-03 20:55:29

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

为了避免在循环客户端连接以广播消息时发生网络调用,服务器线程应将消息添加到队列中以发送到客户端。 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);
        }
    }
}

The simple approach is to use two threads per client connection. One thread handles reading messages from the client the other for sending messages, thereby can send/receive messages from the client simultaneously.

To avoid network calls when looping over the client connections to broadcast a message, the server thread should add the messages into a queue to send to the client. LinkedBlockingQueue in java.util.concurrent is perfect for this. Below is an example:

/**
 * 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);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文