Сервер чата Java - PullRequest
       11

Сервер чата Java

2 голосов
/ 20 июля 2009

Я пишу сервер чата на основе Java, и в настоящее время мой дизайн основан на следующем: - когда человек в комнате чата отправляет сообщение, класс комнаты чата на стороне сервера отправляет одно и то же сообщение каждому участнику комнаты в цикле. Очевидно, что это плохой дизайн, потому что сетевые вызовы делаются отдельным участникам цикла. Следовательно, например, предположим, что в чате находятся 10 человек. Когда один пользователь отправляет сообщение, класс чата отправляет одно и то же сообщение в цикле всем 10 людям. скажем, у 5-го человека в цикле дрянная связь, это повлияет на время, когда шестое ... 10-е лицо увидит сообщение.

если я перейду с одноадресной на многоадресную рассылку для комнаты, как мне получить частный IP-адрес группы многоадресной рассылки для комнаты чата? Кроме того, кажется чрезмерным иметь отдельные группы в чате. Одна из основных проблем заключается в том, что когда я отвечал пользователям в комнате через цикл, метод, который отправлял данные через сокет-соединение, был блокирующим. Следовательно, я думаю, что если я использую неблокирующие сокеты NIO и затем отправляю сообщение получателям в цикле, это решит проблему? Есть ли другие хитрые приемы, которые можно сделать, чтобы оптимизировать отправку данных получателям в комнате?

Ответы [ 3 ]

3 голосов
/ 20 июля 2009

Простая реализация заключается в использовании двух потоков на клиента. Один поток для чтения из сокета, другой для записи в сокет. Если у вас мало клиентов, это будет хорошо. Вам придется познакомиться с NIO, чтобы справиться со многими клиентами. («много» означает, что многопоточная модель не работает хорошо.)

Поток чтения клиента читает все сообщение из сокета и помещает его в очередь в объекте ChatRoom. В комнате чата есть поток, который забирает сообщения из очереди и помещает их в очередь клиента. Пишущий поток клиентов опрашивает свою очередь и записывает сообщение в сокет.

В ChatRoom есть поток для приема соединений, создания клиентских объектов и помещения их в коллекцию. У него есть другой поток, который опрашивает свою очередь сообщений и распределяет сообщения в очереди клиентов.

Apache Mina имеет пример использования NIO

2 голосов
/ 20 июля 2009

Простой подход заключается в использовании двух потоков на клиентское соединение. Один поток обрабатывает чтение сообщений от клиента, другой - для отправки сообщений, тем самым может отправлять / получать сообщения от клиента одновременно.

Чтобы избежать сетевых вызовов при зацикливании клиентских подключений для рассылки сообщения, серверный поток должен добавить сообщения в очередь для отправки клиенту. LinkedBlockingQueue в java.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);
        }
    }
}
2 голосов
/ 20 июля 2009

Я согласен, что последовательное зацикливание ваших получателей было бы плохой идеей. Для этого вы можете рассмотреть возможность использования ThreadPool. Тем не менее, я думаю, что Multicast будет вашим лучшим выбором. Это хорошо подходит для модели чата. Вам нужно будет отправить только один раз, и ваш итеративный подход будет решен. Вы можете получить уникальный идентификатор группы, указав другой порт в своем адресе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...