Ошибки сервера / клиента при отправке слишком большого количества сообщений

#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 , обычно предназначены для чтения с помощью a DataInputStream , а не a Scanner .

Ответ №1:

Расширяя ответ @ EJP, повреждение, с которым вы сталкиваетесь, является результатом какой-либо ошибки прикладного программирования.

  • Если вы используете DataOutputStream для записи данных, вы должны использовать DataInputStream для их чтения. И убедитесь, что последовательность вызовов записи точно соответствует последовательности вызовов чтения.

  • Если вы хотите читать с помощью сканера, вам нужно отформатировать данные как текст и использовать средство записи для их записи. (Убедитесь, что вы используете одну и ту же схему кодирования символов на обоих концах, и избегайте делать неприятные вещи, такие как отображение двоичных данных в текст через String(byte[]) … потому что они имеют тенденцию ломаться.)

  • Если вы либо читаете, либо записываете данные, используя несколько потоков, которые считывают / записывают в один поток, то вам необходимо использовать какую-то блокировку, чтобы гарантировать, что сообщения чередуются правильно / чисто. Потоки обычно НЕ потокобезопасны.


Что касается того, даст ли JSON вам лучшую производительность, вам, вероятно, нужно провести несколько экспериментов, чтобы убедиться в этом. Помимо прочего, это будет зависеть от сложности данных и способа, который вы выбрали для их кодирования в случае, отличном от JSON. (Но я бы ожидал, что DataOutputStream / DataInputStream будут самыми быстрыми, если вы выберете соответствующую кодировку.)

Ответ №2:

сообщение начинает поступать поврежденным

Нет, это не так. Сообщения не поступают поврежденными. Вы просто не синхронизированы, потому что используете плохо определенный протокол приложения. Используйте DataInputStream и DataOutputStream симметрично, как предложил @JimGarrison.