Сортировка данных, полученных через ObjectInputStream

Я сделал мессенджер, который получает данные с сервера через ObjectInputStream. Я хочу иметь возможность извлекать/отправлять сериализуемые файлы, а также иметь возможность извлекать/отправлять сообщения от пользователя.

Я не мог найти хороший способ сортировки между ними (объектами и сообщениями), не вызывая конфликта с обменом сообщениями.

Я пытался использовать два потока для одного и того же сокета (Data*Stream и Object*Stream), и, похоже, все работает нормально, но когда я пытаюсь отправить сообщение с сервера клиенту через Data*Stream, я получаю java.net.SocketException: socket closed на мой клиент. (происходит только тогда, когда я отправляю сообщение)

Может ли кто-нибудь указать мне правильное направление, как я подойду к получению двух разных типов информации через поток? (не ища легкого выхода. Я не хочу делать writeObject("[message]"+input); или подобные дешевые трюки.



(РЕДАКТИРОВАТЬ) РЕШЕНИЕ:

Благодаря janos, он вдохновил меня на написание этого кода. :') Спасибо чувак

Входной приемник:

protected Object data;

public synchronized Object receivedData() throws ClassNotFoundException,
                                                 IOException {
    data = in.readObject();

    if(!(data instanceof String)) {
        retrieveObject();
        data = "";
        System.out.println("Object");
    }
    return data;
}

И ветка сообщений:

ExecutorService pool = Executors.newScheduledThreadPool(1);

private Runnable receiveData;
public void receiveData() {
    receiveData = new Runnable() {

        public void run() {
            String input;
            try {
                while((input = (String) receivedData()) != null) {
                    if(input.length() > 1) 
                        System.out.println(input);

                }
            }catch(IOException | ClassNotFoundException e){ e.printStackTrace();}
        }
    };

    pool.execute(receiveData);
}

Если у вас есть какие-либо советы по улучшению, сообщите мне, и я обновлю этот код.


person Dioxin    schedule 20.10.2013    source источник


Ответы (2)


Вы можете создать родительский класс Message и подклассы DataMessage и TextMessage.

При получении Message вы можете проверить с помощью instanceof его базовый тип и соответствующим образом обработать его.

Эти *Message классы могут заключать в свои переменные-члены любые объекты, которые вы хотите передать между клиентом и сервером. Классы *Message должны быть сериализуемыми, следовательно, все переменные-члены также должны быть сериализуемыми.

Например, учитывая эти типы Message:

class Message {}

class TextMessage extends Message {
    String text;
}

class DataMessage extends Message {
    User user;
}

Вы можете обрабатывать полученные сообщения, например:

Message message = (Message) in.readObject();
if (message instanceof TextMessage) {
    // do something with ((TextMessage)message).text
} else if (message instanceof DataMessage) {
    // do something with ((DataMessage)message).user
}
person janos    schedule 20.10.2013
comment
можете привести пример? если бы я должен был отправить (скажем ..) User.java с сервера -> клиент, объект, отправленный с сервера, является пользователем, а полученный объект - пользователем. Пользователь расширяет объект, поэтому все, что мне нужно будет сделать User user = (User) in.readObject();, но если бы я сортировал с помощью классов, как бы это работало? - person Dioxin; 20.10.2013
comment
Мне может понадобиться некоторое время, чтобы проверить, но это кажется логичным. Я попробую это и сообщу вам, если это сработает. Спасибо :) тоже спасибо за пример, это я и имел в виду - person Dioxin; 20.10.2013
comment
Вместо того, чтобы использовать классы Serializable для сортировки сообщений и объектов, я просто сортировал их по мере их поступления. Сначала я думал, что все, что приходит, будет Object, пока вы его не приведете, но, похоже, это не так. Спасибо за напоминание об «instanceof», не используйте его слишком часто, чтобы держать его в голове. - person Dioxin; 21.10.2013

Я хочу иметь возможность извлекать/отправлять сериализуемые файлы, а также иметь возможность извлекать/отправлять сообщения от пользователя.

Вы можете сделать все это с помощью ObjectInputStream и ObjectOutputStream.

Я не мог найти хороший способ сортировки между ними (объектами и сообщениями), не вызывая конфликта с обменом сообщениями.

Это утверждение бессмысленно, пока вы не укажете «конфликт».

Я пробовал использовать два потока для одного и того же сокета (Data*Stream & Object*Stream)

  1. Вы не можете этого сделать. Используйте один и тот же поток для жизни сокета.

  2. Вам не нужно этого делать. Все, что вы можете сделать с Data*Stream, вы можете сделать с Object*Stream,, потому что Data*Stream реализует Data*Put, а Object*Stream реализует Object*Put, а Object*Put расширяет Data*Put.

и, кажется, все нормально, но когда я пытаюсь отправить сообщение с сервера клиенту через Data * Stream, я получаю java.net.SocketException: сокет закрыт на моем клиенте.

Это означает, что вы закрыли поток и продолжили его использовать. Это вызвано тем, что вы используете два потока. Закрытие любого потока, обернутого вокруг входного или выходного потока сокета, закрывает другой поток и сокет. Вам это не нужно.

(происходит только тогда, когда я отправляю сообщение)

Это происходит только тогда, когда вы читаете или пишете в поток, который уже закрыт.

Может ли кто-нибудь указать мне правильное направление, как я подойду к получению двух разных типов информации через поток?

Просто используйте API Object*Stream.

(не ища легкого выхода. Я не хочу делать writeObject("[message]"+input); или любые подобные дешевые трюки.

Я понятия не имею, почему вы считаете это «дешевым трюком». Вам нужно перестать делать предположения и начать проектировать.

person user207421    schedule 20.10.2013
comment
Не нужно быть грубым. Вы тут немного повторились, и ни капли мне не помогли. Я не столкнулся с каким-либо конфликтом, потому что конфликт был бы очевиден. Если бы я сортировал таким образом, то, если бы я не приложил дополнительных усилий, чтобы сгладить ошибки, пользователи могли бы вручную внести путаницу в систему. - person Dioxin; 20.10.2013
comment
Здесь нет хамства, и ваша попытка внести неуместность такого рода не оценена. Похоже, вы не заинтересованы в выяснении «конфликта», которого хотите избежать. Ваше заявление о том, что это «ни на йоту не помогает [вам]», является заведомо ложным. Я уже говорил вам, что вам не нужно использовать оба типа потоков; Я предоставил строгое доказательство того, почему это так; и я также объяснил, почему вы столкнулись с исключением. Очевидно, вы больше заинтересованы в споре, чем в решении вашей проблемы. Извини, что побеспокоил. - person user207421; 20.10.2013
comment
1. Если «конфликт не имеет отношения к проблеме», то почему вы вообще его упомянули? 2. Если для вас было очевидно, что вы не можете использовать два потока на одном базовом потоке, закрыть один из них, а затем использовать другой без получения исключения, то почему именно вы это сделали? 3. Какую именно «помощь, которой нет», я заставил вас искать? 3. Object*Streams API является ответом на ваш вопрос. Если вы собираетесь жаловаться на помощь, которую вам любезно оказывают здесь, по крайней мере приложите некоторые усилия, чтобы это выглядело правдоподобно. - person user207421; 20.10.2013
comment
Пожалуйста, не касайтесь любительской психологии. java.net.SocketException: socket closed означает, что вы закрыли его. OK? - person user207421; 21.10.2013
comment
EJP, ты выглядишь расстроенным, как дела, приятель? Не нужно выплескивать свой гнев на stackoverflow... - person J Code; 19.01.2014