Поток вывода данных не сбрасывается
-
13-09-2019 - |
Вопрос
У меня есть Java-клиент, который отправляет строки UTF-8 на C # TCP-сервер, я использую DataOutputStream для отправки строк.Код выглядит примерно так:
public void sendUTF8String(String ar) {
if (socket.isConnected()) {
try {
dataOutputStream.write(ar.getBytes(Charset.forName("UTF-8")));
dataOutputStream.flush();
} catch (IOException e) {
handleException(e);
}
}
}
Проблема в том, что флеш, похоже, работает неправильно.Если я отправляю две строки близко друг к другу, сервер получает только одно сообщение с обеими строками.Все это работает, если я выполняю Thread.sleep (1000) между вызовами, это, очевидно, не решение.Что я упускаю из виду?
Решение
flush()
не гарантирует, что пакет данных будет отправлен.Ваш стек TCP / IP может свободно объединять ваши данные для достижения максимальной эффективности.Хуже того, вероятно, между вами и вашим пунктом назначения есть множество других стеков TCP / IP, и они могут свободно делать то же самое.
Я думаю, вам не следует полагаться на пакетирование.Вставьте логический ограничитель в ваши данные, и вы будете в безопасности.
Другие советы
Вам не следует беспокоиться о том, как данные разбиваются на пакеты.
Вы должны указывать длину строки в своих сообщениях, а затем на принимающей стороне вы бы сначала прочитали эту длину.Так, например, для отправки вы бы сделали
byte[] arbytes = ar.getBytes(Charset.forName("UTF-8"));
output.writeInt(arbytes.length)
output.write(arbytes)
и затем в своем ридере вы делаете
byte[] arbytes = new byte[input.readInt()];
for(int i = 0; i < len; i++){
arbytes[i] = input.read();
}
//convert bytes back to string.
Вы не можете просто вызвать input.read(arbytes), потому что функция read не обязательно считывает всю длину массива.Вы можете выполнить цикл, в котором вы читаете фрагмент за раз, но код для этого немного сложнее.
В любом случае, вы поняли идею.
Кроме того, если вы действительно хотите контролировать, что отправляется в каких пакетах, вы можете использовать Сокеты дейтаграмм, но если вы сделаете это, то доставка пакета не гарантируется.
Сокет отправляет поток данных, а не сообщений.Вам не следует полагаться на то, что получаемые вами пакеты будут того же размера, что и отправленные.Пакеты могут быть сгруппированы вместе, как вы уже видели, но они также могут быть разбиты.Воспользуйтесь предложением @Chad Okere о том, как убедиться, что вы получаете блоки так же, как они были отправлены.
Однако в вашем случае вы можете просто использовать
dataOutputStream.writeUTF(ar); // sends a string as UTF-8
и
String text = dataInputStream.readUTF(); // reads a string as UTF-8