UDP-сокет Datagram получает пакет 2x, чтобы получить полное сообщение - PullRequest
1 голос
/ 30 декабря 2011

Я создаю экспериментальный игровой сервер в Java.

Клиент отправляет:

length: 22\r\n
playerId: 0\r\n
\r\n\r\n
this is a test message

Java код для получения сообщения:

String message = "";

byte[] buf = new byte[20];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socketServer.receive(packet);
message += new String(buf, "UTF8");

buf = new byte[20];
packet = new DatagramPacket(buf, buf.length);
socketServer.receive(packet);
message += new String(buf, "UTF8");

Он не получает 40 байтов сообщения, отправленного клиентом, он получает 20 байтов и на втором socketServer.receive(packet) зависает для нового сообщения.

Причина по определению:

Этот метод блокируется до получения дейтаграммы. Поле длины объект пакета дейтаграммы содержит длину полученного сообщение. Если сообщение длиннее, чем длина пакета, сообщение обрезано.

Мне нужно иметь возможность прочитать 20 байтов сообщения и еще 20 байтов сообщения. Как этого достичь?

Мне это нужно, потому что я не уверен, как долго сообщение будет. Я хочу что-то вроде этого:

String message = "";
while (!message.contains("\r\n\r\n")) { //"\r\n\r\n" marks end of message
    byte[] buf = new byte[20];
    DatagramPacket packet = new DatagramPacket(buf, buf.length);
    socketServer.receive(packet);
    message += new String(buf, "UTF8");
}

Получается полное сообщение, если сообщение заканчивается на \r\n\r\n.

Это нужно сделать по протоколу UDP. Я новичок в сокетах в Java, но я предполагаю, что есть что-то для этого, просто не могу найти это. Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 30 декабря 2011

UDP не предназначен для чтения переменной длины - каждый read() [или recv()] будет соответствовать одному write() [или send()] на сервере.

Если вы толькопрочитайте 20 байтов 40-байтового пакета, остальные байты будут отброшены.

Вам необходимо создать достаточно большой буфер для приема всего пакета (не более 65536 байтов, если ваша сеть правильно обрабатывает фрагментацию), а затем прочитать всепакет за один раз.

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

2 голосов
/ 30 декабря 2011

Если вы пишете 40 байтов, вы должны получить 40 байтов.Если вы напишите 40 байтов, а ваш буфер будет только 20, то вы потеряете 20 байтов.

Q: Так почему бы не сделать ваш буфер 256 байтов (например) и читать то, что вы получаете?

В: Если вам нужно, чтобы «сообщение» состояло из двух частей ... тогда почему бы просто не отправить два сообщения?

...