Приложение на сервере Dart на стороне сервера получает строку JSON из сокета. Строка генерируется кодом Java. Когда строка отправляется в сокет в коде Java, он кодируется в UTF8, а два байта, короткий int, добавляются к строке. Значение этого короткого числа - это количество байтов в строке + 2.
Мне нужно извлечь это значение как int для обработки строки, но ничего, что я пробовал, сработало. Он умирает в JSON.decode (ниже), потому что он встречает начало другой строки JSON. Первый байт второй строки - это начало с длиной второй строки JSON. Две строки имеют длину менее 40 символов.
(Мне нужно будет добавить длину к строкам, отправленным из Dart на Java.)
Строка Java
out.writeUTF(json); // converts and writes to the socket stream.
Метод бокового кода сервера Dart
handleJavaSocket(Socket javasocket){
javasocket.transform(UTF8.decoder).listen((String socketString){
var truncated = socketString.substring(2);
String message = JSON.decode(truncated); // dies here
// more code
}, onError: (error) {
print('Bad JavaSocket request');
});
}
Одна из строк JSON перед кодированием
{"target":"DOOR","command":"OPEN"}
Я не мог найти способ преобразования двух байтовых заголовков в целое число, особенно потому, что один байт может быть 0, а некоторые строковые методы рассматривают это как ограничитель строк.
Поскольку сообщение из приложения Java всегда будет состоять из заголовка, за которым следует сообщение, я игнорирую заголовок и разбираю сообщения (сообщения) из потока, добавляя их в список (чтобы повторить их как проверку)
Затем я пересекаю список и моделирую заголовок, записывая 0 байт, за которым следует размер сообщения в поток потока, за которым следует сообщение. Это не сработает, так как длина сообщений больше 255, но я не ожидаю, что они будут даже близки к этому размеру.
следует отметить, что приложение Дарт и приложение Java находятся на одной машине.
handleJavaSocket(Socket javasocket){
// echo socket
javasocket.transform(UTF8.decoder).forEach((item) {
var start = 2;
var end = -1;
var messages = new List<String>();
while((++end < item.length) && (end = item.indexOf('}',end)) != -1) {
messages.add(item.substring(start, ++end));
start = end + 2;
}
for(var message in messages) {
// header message length as two bytes
javasocket.writeCharCode(0); // max length 254
javasocket.writeCharCode(message.length);
javasocket.write(message); // <== send
}
});
}
Итак, вы всегда отправляете как [sizeuper8, sizelower8,..utf8-string...] в качестве границ ваших сообщений? Декодирование UTF8 не ожидает длины в качестве параметра и рассматривает два байта как unicode (возможно, null, за которым следует символ).
В настоящее время я работаю над StreamBuffer for Quiver (https://pub.dartlang.org/packages/quiver), который позволит вам подключить сокет к буферу, который дает вам:
read(2).then((bytes) => read(bytes[1]<<8|bytes[2]).then((string) => UTF8.decode(string)));
После этого вы можете опубликовать декодированную строку для всех, что вам нравится, но она должна дешифровать ваши данные.
Текущий запрос на извлечение (выполняется работа): https://github.com/google/quiver-dart/pull/117