Java SocketServer с несколькими клиентами - StreamCorruptException - PullRequest
3 голосов
/ 25 июня 2011

Заявка

Я пишу клиент-серверное приложение на Java, которое взаимодействует путем отправки объектов через сокеты с использованием классов ObjectStream. Каждый узел в приложении выглядит примерно так:

class Node {
  SocketServer server;
  Socket[] clients;
}

Здесь переменная server - это сокет, на котором слушает этот узел, а переменные client - это сокеты, на которых слушают другие узлы, и на которые этот узел отправляет объекты.

Код, который я использую для записи объектов в один из клиентских сокетов, выглядит следующим образом:

void sendMessage(Message<B, F> msg) throws IOException {
    ObjectOutputStream writer = getWriter();
    writer.writeObject(msg);
    writer.flush();
}

private ObjectOutputStream writer;

ObjectOutputStream getWriter() throws IOException {
    if (writer == null)
        writer = new ObjectOutputStream(
            new BufferedOutputStream(client.getOutputStream()));
    return writer;
}

А код, который я использую для обработки соединений и чтения объектов из сокета сервера узла, выглядит следующим образом:

// the handler will listen for connections
final Thread handler = new Thread(new Runnable() {

    public void run() {
        try {
            // create a new thread to handle the client
            final Socket client = server.accept();
            final Thread thread = new Thread(new Runnable() {

                public void run() {
                    final ObjectInputStream reader;
                    try {
                        reader = new ObjectInputStream(client.getInputStream());
                        while (true) {
                            try {
                                val msg = reader.readObject();
                                messages.add((Message<B, F>) msg);
                            }
                            catch (EOFException e) {
                                // i noted it seemed to throw eofexceptions
                            }
                            catch (IOException e) {
                                // do something
                            }
                        }
                    }
                    catch (IOException e) {
                        // do something
                    }
                }
            });
          thread.start();
        } catch (IOException e) {
            // do something
        }
    }
});
handler.start();

Проблема

Я думаю, что я делаю что-то не так с сокетами здесь. Все работает нормально, когда каждый сервер подключен только к одному клиенту. Однако, когда несколько клиентов общаются с одним и тем же сервером, дела идут плохо, и я получаю StreamCorruptedException от ObjectInputStream и другое странное поведение (добавление экземпляра сообщения UpdateRequest и получение экземпляра Integer (0) и некоторых исключений, например.)

Моя интуиция подсказывает мне, что два потока объектов / байтов так или иначе смешиваются, и это приводит к странным результатам при попытке десериализации объектов. У меня вопрос: почему так происходит, что я делаю неправильно, и как я могу это исправить?

Ответы [ 2 ]

1 голос
/ 25 июня 2011

У вас есть массив сокетов, но у вас, похоже, нет массива писателей и читателей. Таким образом, вы, вероятно, используете один и тот же модуль записи и чтения для всех подключений.

На самом деле у вас должен быть объект Connection для соединения, который реализует Runnable и в котором в качестве членов экземпляра используются Socket, Writer и reader.

Также, когда вы перехватываете EOFException, вы должны выйти из цикла и закрыть программу записи.

0 голосов
/ 03 августа 2011

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

...