вам не нужно повторно инициализировать буфер в пакете, вам просто нужно сбросить содержимое буфера до того, каким оно было изначально (т.е. вам нужно заполнить принимающий массив нулями).
Вызов:
Arrays.fill (buf, (byte) 0);
на стороне сервера сбросит массив в ноль, поскольку массивы в Java передаются по ссылке, а не передаются-by-value (т. е. имеющаяся у вас ссылка на содержимое массива такая же, как и ссылка на DatagramPacket, поэтому вы можете изменить ее, не используя методы DatagramPacket).
Сказав, что высериализация / десериализация данных не идеальна.Было бы лучше использовать ByteArrayOutputStream и ByteArrayInputStream, обернутые вокруг буфера отправки и получения, а затем DataOutputStream / DataInputStream, обернутый вокруг них.Это позволит вам писать и читать строку в четко определенном формате, который, вероятно, будет хранить длину строки, так что любые оставшиеся данные в буфере будут игнорироваться в любом случае.Правильная сериализация / десериализация таким способом также устранит необходимость удаления символа «черный бриллиант».
DataOutputStream.writeUTF
Если вы заинтересованы в рассужденияхза этим стоит использование сериализации по умолчанию для java.lang.String (getBytes () и new String (byte [])), а также того, как заполняется пакет UDP.Я попытаюсь свести его к ключевым моментам:
Внутреннее представление Java для объектов String не является байтовым массивом - это массив символов.Символы Java не совпадают с байтами - один символ на самом деле составляет 2 байта, потому что он должен иметь возможность представлять больше, чем просто латинский алфавит (acbd ...), он должен поддерживать другие символы из других языков / культур, такие как вещи изКириллица, кандзи и т. Д. И одного байта недостаточно (один байт дает вам 256 возможностей, 2 байта - 65536).
В результате при вызове getBytes () Java должна использовать некоторую «схему» (кодирование), чтобы превратить этот массив символов в массив байтов (сериализация).Детали этого не имеют большого значения, но когда вы отправляете первый кусок байтов (скажем, длиной 10 байтов), вы читаете пакет в гораздо больший буфер (1024 байта).Затем вы просите Java String десериализовать весь этот буфер, а не только 10 байтов.
Схема (кодирование) не знает, что имеет дело только с первыми 10 байтами, поэтому она пытается декодировать все 1024 байта,и затем вы получите странные символы в вашей строке, такие как черный ромб, или (где вы поместили некоторые другие данные после 10 байтов, отправив «привет»), вы получите символы из предыдущего приема, смешанные в вашей строке.
Использование write / readUTF запишет длину байтового массива, а также данные, поэтому при повторном чтении он узнает, что он должен прочитать только первые 10 символов (или сколько их допустимо).