#java #tcp #java.util.scanner #numberformatexception #dataoutputstream
#java #tcp #java.util.scanner #исключение numberformatexception #dataoutputstream
Вопрос:
У меня возникает проблема в многопользовательской игре TCP на сервере / клиенте всякий раз, когда я пытаюсь отправить слишком много сообщений за короткое время (обычно более 20 сообщений в дуге 20 миллиметров). Через некоторое время сообщения начинают поступать по какой-то причине поврежденными (например, с целыми числами вместо строк, которые обычно вызывают у меня исключение NumberFormatException).
Я отправляю информацию в виде строк, используя DataOutputStream, и считываю их с помощью сканера.
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
in = new Scanner(inputStream);
out = new DataOutputStream (outputStream);
Мои вопросы: должен ли я использовать что-то отличное от комбинации DataOutputStream / Scanner? Есть ли более быстрая комбинация? Должен ли я преобразовывать строки в байты перед их отправкой?
Отправляемые мной строки обычно состоят как из целых чисел, так и из строк, например «m 2 215 123» или «ep 2».
Комментарии:
1. Эх .. почему бы просто не отправить JSON? Разве это не проще, чем ручной синтаксический анализ и сериализация данных?
2. Хорошо.. Я вообще об этом не думал. Что делать, если мне нужно отправлять двумерный массив строк размером 8×18 с использованием JSON каждые 18 миллиметров или около того. Действительно ли синтаксический анализ JSON быстрее? Обновления происходят так быстро, потому что мы говорим об игре. И сообщения обычно являются врагами, перемещающимися по карте.
3. Я не уверен, что это действительно быстрее, просто в вашем случае это звучит менее подверженным ошибкам, и вы не почувствуете себя странно
NumberFormatExceptions
, сериализация ваших собственных данных всегда должна быть вашим последним средством.4. Данные , сериализованные с помощью
DataOutputStream
, обычно предназначены для чтения с помощью aDataInputStream
, а не aScanner
.
Ответ №1:
Расширяя ответ @ EJP, повреждение, с которым вы сталкиваетесь, является результатом какой-либо ошибки прикладного программирования.
-
Если вы используете
DataOutputStream
для записи данных, вы должны использоватьDataInputStream
для их чтения. И убедитесь, что последовательность вызовов записи точно соответствует последовательности вызовов чтения. -
Если вы хотите читать с помощью сканера, вам нужно отформатировать данные как текст и использовать средство записи для их записи. (Убедитесь, что вы используете одну и ту же схему кодирования символов на обоих концах, и избегайте делать неприятные вещи, такие как отображение двоичных данных в текст через
String(byte[])
… потому что они имеют тенденцию ломаться.) -
Если вы либо читаете, либо записываете данные, используя несколько потоков, которые считывают / записывают в один поток, то вам необходимо использовать какую-то блокировку, чтобы гарантировать, что сообщения чередуются правильно / чисто. Потоки обычно НЕ потокобезопасны.
Что касается того, даст ли JSON вам лучшую производительность, вам, вероятно, нужно провести несколько экспериментов, чтобы убедиться в этом. Помимо прочего, это будет зависеть от сложности данных и способа, который вы выбрали для их кодирования в случае, отличном от JSON. (Но я бы ожидал, что DataOutputStream / DataInputStream будут самыми быстрыми, если вы выберете соответствующую кодировку.)
Ответ №2:
сообщение начинает поступать поврежденным
Нет, это не так. Сообщения не поступают поврежденными. Вы просто не синхронизированы, потому что используете плохо определенный протокол приложения. Используйте DataInputStream и DataOutputStream симметрично, как предложил @JimGarrison.