PDA

Просмотр полной версии : как пользоваться byteArray.readInt()?


anmelegov
18.04.2012, 17:17
собственно вопрос в заголовке... у меня есть byteArray, в нем числа, если я читаю из него 4 байта в другой byteArray, а потом тот byteArray читаю методом readInt, то получается, а если я из исходного массива просто несколько раз вызываю readInt, то первое число читается, а потом какая-то фигня идет дальше... такое ощущение что он сдвигает поинтер не на 4 байта

КорДум
18.04.2012, 17:24
Так и читается.
// имеем 8 байт
bt.readInt();
// осталось 4 байта
bt.readInt();
// массив bt пуст
Иными словами, у Вас после первых четырех байт идет вовсе не инт, а short, byte, UTFString или нечто иное.

anmelegov
18.04.2012, 17:24
очень сложно написал, напишите мне кодом просто чтоб я понял... в строке идет 2 пропуска строки, потом идут 4 инта, как это прочитать?

Добавлено через 1 минуту
Так и читается.
// имеем 8 байт
bt.readInt();
// осталось 4 байта
bt.readInt();
// массив bt пуст
Иными словами, у Вас после первых четырех байт идет вовсе не инт, а short, byte, UTFString или нечто иное.

как посмотреть структуру массива который приходит?

Добавлено через 3 минуты
когда я делаю readBytes(x, offset), то offset такое ощущение что не сначала "сдвигает" окно, а сконца

КорДум
18.04.2012, 17:32
Вот пример:
//пакет выглядит так:
//type (1b) length (2b) message (Nb)
type = byteArray.readByte();
length = byteArray.readShort();
message = byteArray.readBytes(0, length);
Это не псевдокод. При чтении byteAviables (или как там это свойство) уменьшается на количество считанных байтов. "Каретка" четния тоже смещается.

Добавлено через 48 секунд
в строке идет 2 пропуска строки
А это я не понял.

anmelegov
18.04.2012, 17:35
в сокет приходит сначала 2 перевода каретки, потом 16-тиричное число, а потом нужные мне байты

КорДум
18.04.2012, 17:39
Перевод каретки виндовый или юниксовый? В первом случае это 2 байта, во втором 1 на один перевод каретки.
readShort();
readShort();
var numb:int = readInt();
var str:String = readUTFBytes(0, bytesAvailable);
Это если за раз пришел один пакет, полностью и не склеенный.

anmelegov
18.04.2012, 17:43
можно как-нибуть во flashDevelop посмотреть структуру массива который приходит на сокет? или надо на угад парсить? я даже не знаю какой там endian

КорДум
18.04.2012, 17:45
endian посмотреть можно, поставив брейкпоинт и глянув в дебаггере. А вот содержимое, к сожалению, нет. Самого это несколько разочаровывало, приходилось наугад и трейсами.

anmelegov
18.04.2012, 17:46
трейсом байты не выводятся =)

-De-
18.04.2012, 17:51
Написать трейсилку байтаррея на полчаса с перекуром задачка.

anmelegov
18.04.2012, 17:52
похоже сервер не правильно присылает, потому что я протрейсил длину массива и там очевидно не хватает байтов =)

gloomyBrain
18.04.2012, 17:58
Ну, в общем-то там и не обязательно должны быть ВСЕ байты. Потому как по сети информация передается пакетами, размер которых определяется пройденными по пути маршрутизаторами.
То есть если Вам отправили 100 байт, это значит что вам может прийти:
- 2 по 50
- 1 по 100
- 2 по 25 + 1 по 50

Для того чтобы удостовериться в целостности сообщения, как правило, записывают длину сообщения в его первые 2 байта. А на принимающей стороне принимаем 2 байта, читаем их (получаем ожидаемую длину) и ждем пока придет столько, сколько указано в длине.

anmelegov
18.04.2012, 18:46
у меня обмен идет через tcp соединение, а не через udp

wvxvw
18.04.2012, 21:44
Есть замечательная программа, практически обязательный инструмет любого веб-разработчика - Wireshark. :P Показывает всю возможную информации о том что и куда пересылалось по сети. А еще и бесплатно!

anmelegov
19.04.2012, 00:45
да я уже поставил =) но поскольку косяк не с моей стороны я особо не стал заморачиваться, жду пока пацаны поправят серверсайд

-De-
19.04.2012, 12:34
gloomyBrain пишет именно про tcp, про Socket, как уже не раз писали, это поток (XMLSocket по-моему сам склеивает, использует 0 байт как разделитель как альтернативу "записывают длину сообщения в его первые 2 байта"). В udp по-моему как раз есть пакеты, т.е. отосланное не может побиться.

anmelegov
19.04.2012, 12:58
TCP — это транспортный механизм, предоставляющий поток данных, с предварительной установкой соединения, за счёт этого дающий уверенность в достоверности получаемых данных, осуществляет повторный запрос данных в случае потери данных и устраняет дублирование при получении двух копий одного пакета (см. также T/TCP). В отличие от UDP гарантирует целостность передаваемых данных и уведомление отправителя о результатах передачи.
http://ru.wikipedia.org/wiki/TCP

-De-
19.04.2012, 14:00
Но гарантий, что данные придут одним куском - нет. Ещё раз, интерфейс tcp socket - это поток. Что это может означать - gloomyBrain хорошо описал. Все нормальные сетевики это знают, спорить смысла нет, можно не верить, конечно)

gloomyBrain
19.04.2012, 14:17
гарантирует целостность передаваемых данных и уведомление отправителя о результатах передачи

Вот здесь вообще написано о том, что приходит все что отправлено. И больше ничего. Однако, это вовсе не означает что получены данные будут теми же порциями, что и при отправке.

Короче, если разберетесь, то вот:

package nq.net.connections.buffered {

import flash.errors.IllegalOperationError;
import flash.events.ProgressEvent;
import flash.utils.ByteArray;
import nq.net.connections.ASocketConnection;

[Event(name = "bufferedSocketMessage", type = "nq.net.connections.buffered.SocketMessageEvent")]

/**
* Буферизированное соединение с сокет-сервером
*
* @author gloomybrain
*/
public final class BufferedSocketConnection extends ASocketConnection {

private var _bytesLeft:uint = 0;
private var _tempMessage:SocketMessage = null;

private var _maxMessageSize:uint;

/**
* @param maxMessageSize Максимальный размер сообщения в байтах
*/
public function BufferedSocketConnection(maxMessageSize:uint = 1500) {

super();

if (maxMessageSize > 0xFFFF - 1) throw new ArgumentError("Максимальная длина сообщения выходит за границы допустимого диапазона!");
_maxMessageSize = maxMessageSize;

super._socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData);

}

/**
* Отправить сообщение на сервер
*
* @param message
*/
public function send(message:SocketMessage):void {

if (!message) throw new ArgumentError("Параметр должен быть не нулевым!");
if (message.data && (message.data.length > _maxMessageSize)) throw new ArgumentError("Длина отправляемого сообщения превышает допустимый предел!");

message.toBytes(super._socket);
super._socket.flush();

}

private function onSocketData(event:ProgressEvent = null):void {

if (!super._socket.connected) return;

if (_bytesLeft == 0) {

if (super._socket.bytesAvailable < 3) return;

var bodyLength:uint = super._socket.readUnsignedShort();
var bodyType:uint = super._socket.readUnsignedByte();

if (bodyLength > _maxMessageSize) throw new IllegalOperationError("Длина принятого сообщения превышает допустимый предел!");

_bytesLeft = bodyLength - 1;

if (_bytesLeft != 0) {

_tempMessage = new SocketMessage(bodyType, new ByteArray());
return onSocketData();
}

super.dispatchEvent(new SocketMessageEvent(SocketMessageEvent.MESSAGE, new SocketMessage(bodyType)));

}else {

if (super._socket.bytesAvailable < _bytesLeft) return;

super._socket.readBytes(_tempMessage.data, 0, _bytesLeft);
super.dispatchEvent(new SocketMessageEvent(SocketMessageEvent.MESSAGE, _tempMessage));

_bytesLeft = 0;
_tempMessage = null;

if (super._socket.bytesAvailable > 0) return onSocketData();

}

}

/**
* Максимальный размер сообщения в байтах
*/
public function get maxMessageSize():uint {
return _maxMessageSize;
}


/* INTERFACE nq.core.IDestroyable */

/**
* @inheritDoc
*/
override public function destroy():void {

_bytesLeft = 0;
_tempMessage = null;

super._socket.removeEventListener(ProgressEvent.SOCKET_DATA, onSocketData);

super.destroy();
}

}

}