Обеспечение правильного ответа на запрос клиента - PullRequest
0 голосов
/ 26 апреля 2011

Ищем предложения по следующей проблеме.

Я работаю над приложением (клиентом), которое использует один сокет TCP для чтения и записи сообщений на сервер.

Сообщение - это один из нескольких предопределенных типов, который будет обработан по прибытии.

Сервер может транслировать сообщение в любое время.

Клиент отправит сообщение на сервер и ожидает ответа. Однако (и здесь мой вопрос приходит), я не могу читать из сокета, чтобы получить это сообщение, так как понятия не имею, когда оно может быть доставлено. В большинстве случаев ответное сообщение клиента будет доставлено сразу после запроса клиента. Однако иногда другое широковещательное сообщение будет отправлено первым.

Канал чтения сокета помещается в очередь блокировки одним потоком производителя. В отдельном потоке потребителей все сообщения удаляются из очереди и отправляются для дальнейшей обработки. Чтобы получить ожидаемые клиентские ответы, должен ли я использовать идиому источника событий / слушателя, чтобы мои клиенты были уведомлены, когда их (и если) ответы будут получены?

Спасибо за любые предложения.

РЕДАКТИРОВАТЬ: Я думаю, что мой вопрос неясен, так как предложения до сих пор не касаются проблемы под рукой. В конце концов, я использовал идиому источника / слушателя события, чтобы справиться с этим. Еще раз спасибо за ошибку, но я считаю, что это закрыто. Модератор может даже захотеть удалить этот вопрос.

Ответы [ 2 ]

0 голосов
/ 26 апреля 2011

Вы можете реализовать это с помощью слушателя и пула кэшированных потоков. Таким образом, вы можете создать класс Runnable, который выполняет обработку сообщения. Затем создайте класс слушателя, который просто создает экземпляр сокета (или сокета сервера) и создает пул потоков. В вашем классе слушателя создайте бесконечный цикл while, который прослушивает входящие запросы и передает socket.accept в конструктор вашего объекта runnable, чтобы он мог обрабатывать любые входные данные из сокета.

Код будет выглядеть примерно так:

public class MessageHandler implements Runnable {

    String msg = "";
    Socket socket = null;
    BufferedReader in = null;
    PrintWriter out = null;

    public void MessageHandler(ServerSocket socket){
        this.socket = socket;
    }

    @Override
    public void run(){
        //Message read from socket
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        System.out.println("Message: " + in.readLine());

        //Reply send back through same socket
        out = new PrintWriter(socket.getOutputStream(), true);
        out.println("MESSAGE RECEIVED. THANKS.");
    }
}

И ваш класс прослушивания будет выглядеть примерно так:

public class SocketListener {

    ServerSocket socket = null;
    ExecutorService threadExecutor = null;
    Runnable runnable = null;

    public static void main (String[] args){
        socket = new ServerSocket(8181);

        /* Socket will always be listening, when a request arrives a thread will handle
         * the incoming stream.
         */
        while(true) {
            threadExecutor = Executors.newCachedThreadPool();
            runnable = new MessageHandler(socket.accept);
            threadExecutor.execute(runnable);
        }
    }
}

Я не уверен, скомпилируется ли этот код, но реализация вашего сервера может выглядеть очень похоже на это и будет масштабируемой и устойчивой.

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

0 голосов
/ 26 апреля 2011

Это прекрасная возможность использовать механизмы сериализации Java.Вы можете сделать что-то вроде этого (предположим, что вы перехватываете все соответствующие исключения, которые для краткости опущены)

class ClientListeningThread {

    ObjectInputStream in;
    ObjectOutputStream out;

    ClientListeningThread(Socket s) {
        in = new ObjectInputStream(s.getInputStream());
        out = new ObjectOutputStream(s.getOututStream());
    }

    public void run() {
        while(true) {
            ClientMessage message = (ClientMessage)in.readObject();
            engine.addMessage(this,message); // add to the message queue, signifiying which listening thread to give the response to
        }
    }

    public void send(ServerMessage message) {
        out.writeObject(message);
    }

}

Ваши сообщения могут даже иметь обратные вызовы для

класса LoginMessage {

public final String username;
public final String password;

public LoginMessage(String username, String password) {
    this.username = username;
    this.password = password;
}

public void callback(ClientListeningThread thread, ServerProcessor engine) {
    ServerMessage response = engine.attemptLogin(username,password);
    thread.send(response);
}

}

А у тебя в двигателе

while(!requests.isEmpty()) {
    ClientRequest request = requests.poll();
    ClientListeningThread = request.thread;
    ClientMessage message = request.message;
    request.callback(thread,this);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...