Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Кл.-серверное приложение. Протокол взаимодействия.


Автор: ci5 29.12.2012, 19:51
Здравствуйте.
Сервер может обрабатывать около 300 соединений. Думал реализовать всё на сокетах, но есть одно но. Надо при определенных событиях сервера, делать уведомление всех клиентов об этом событии. Что-то некого бродкаста должно быть. Вот тут то я и не совсем понимаю, как это на сокетах реализовать(или вовсе не на сокетах). Реализовать через POST и GET запросы я так понимаю тут невозможно, ибо нужно держать соединение с клиентами и уведомлять их о событиях независимо от передачи ими данных, что HTTP не поддерживает. Кто что может подсказать по данному вопросу? Клиенты сами подключаются и отключаются.
Заранее спасибо

Автор: jManiak 29.12.2012, 23:15
А чем вам все-таки сокеты не нравятся? Рассылка всем (или некоторым) делается на ура.

Автор: danilych 30.12.2012, 01:44
посмотри atmosphere фреймворк и cometD фреймворк - небольшое описание http://www.ibm.com/developerworks/ru/library/wa-reverseajax4/

Автор: ci5 30.12.2012, 11:58
jManiak, я просто работал с клиент-серверными приложениями на сокетах, там суть была в запросе клиента и ответа сервера. И друг от друга они ждут указаний на блокирующих методах.
Код

                switch(switchConnection) { 
                    case SEND_DATA: 
                        oos.writeObject(chiefs);
                        oos.writeObject(staff);
                        closeStreams(); 
                        break;
                    case ACCEPT_DATA:
                        chiefs = (List)ois.readObject();
                        staff = (List)ois.readObject();
                        parsing.setChiefs(chiefs);
                        parsing.setStaff(staff);
                        parsing.saveData();
                        parseData(); 
                        closeStreams();
                        break;
                }

Вот как делал до этого. Но проблема была в том, что я делал подключение и указывал команду. А тут надо держать соединение. А как сделать спонтанно, что бы можно было клиентам уже подключенным передать команду, ума не приложу. Извиняюсь если глупость спрашиваю, но понять вот этот момент никак не могу, как это будет реализовано. Делать два соединения? Один для общения обычными командами, а другой для слушания сервера? 
danilych, к сожалению не могу использовать посторонние фреймворки. Исключительно Java SE. Но за помощь всё равно спасибо. 

Автор: jManiak 30.12.2012, 14:25
А кто мешает держать соединение на сокетах? Они собственно для этого и предназначены. Не нужно закрывать соединения. Сохраняйте у себя объекты соединений и когда потребуются, используйте их.

Автор: COVD 30.12.2012, 17:58
Цитата

Вот тут то я и не совсем понимаю, как это на сокетах реализовать(или вовсе не на сокетах). Реализовать через POST и GET запросы я так понимаю тут невозможно, ибо нужно держать соединение с клиентами и уведомлять их о событиях независимо от передачи ими данных, что HTTP не поддерживает.

Любая коммуникация между компьютерами реализуется на сокетах (ничего другого нет). Но по-разному. Если отправляются байтовые сообщения, то, очевидно, речь идет о  протоколе на основе TCP (если используются TCP сокеты) . Если в сообщения добавляются текстовые заголовки, составленные в соответствии со спецификацией HTTP, то получаем  HTTP протокол. Если клиентские приложения соединяются с сервером через интернет, то HTTP  предпочтительнее, так это стандарт для интернета и позволяет избежать ограничений, связанных с файерволами.

Чтобы сервер мог уведомлять клиентов, сервер должен держать соединения с клиентами. Или клиенты должны сами периодически опрашивать сервер. В этом случае задержка уведомления зависит еще и от периода опроса.

HTTP позволяет организовать псевдопостоянные соединения. Сервер, отвечая на запрос клиента, может это делать бесконечно долго. Однако бесконечный ответ иногда приводит к тому, что антивирус на клиенте не пропускает ответ, пока не получит конец. Поэтому идеальным является серия относительно длительных соединений. Технологии comet , ajax как раз и используют возможности HTTP для реализации серии относительно длительных соединений.

 

Автор: ci5 6.1.2013, 13:25
Благодарю за ответы. 
COVD, к сожалению, нет возможности пользоваться ничем, кроме стандартного JavaSE. 
У меня могут передаваться как массив со строками, так и булева значения. В принципе, можно переделать архитектуру так, что бы можно было передавать только текстовые сообщения. 
Но тут, как новичка в HTTP, интересует три вопроса: 
1. Как понимать, что клиент отключился? 
2. Как держать соединение с клиентом? Их же надо будет уведомлять о событиях, независимо от их действий. Сервер же ничего не знает про клиентов, он может только что-то отправить в отклик, когда клиент что-то запросит. 
3. Как это реализовать на SE? Раньше только на EE реализовывал, на сервлетах, где обработчиком был веб сервер. А тут как? 
Или всё же тут сокеты предпочтительней? 

Автор: jk1 6.1.2013, 19:58
Цитата

3. Как это реализовать на SE? Раньше только на EE реализовывал, на сервлетах, где обработчиком был веб сервер. А тут как? 


Код

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class Test {

    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
        server.createContext("/test", new MyHandler());
        server.setExecutor(null); // creates a default executor
        server.start();
    }

    static class MyHandler implements HttpHandler {
        public void handle(HttpExchange t) throws IOException {
            String response = "This is the response";
            t.sendResponseHeaders(200, response.length());
            OutputStream os = t.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }

}

Автор: COVD 7.1.2013, 19:58
На сокетах придется самому программировать парсирование http заголовков.
Проще использовать встроенный в SE веб-сервер, пример которого привел jk1.
Для получения уведомлений клиенты должны периодически слать запрос (polling). Надо только самому реализовать сессии клиентов и туда класть уведомления. Если запросы с определенным jsessionid прекратили поступать, сессия через некоторое время удаляется (по таймауту). 

Автор: ci5 9.1.2013, 14:15
Благодарю! Но я реализовал это дело через сокеты всё же. Клиент в два потока, первый посылает команды, второй принимает. Сервер же в основном потоке делает рассылку всем, либо кому надо. В потоках непосредственно для клиентов получает данные. Получилось довольно гибко. 
Но возьму на заметку про SE веб сервер. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)