рекомбинировать разделенный TCP-пакет с флеш-сокетами - PullRequest
1 голос
/ 20 мая 2011

У меня есть программа на c ++, которая отправляет флеш-плейер сокетом в 23723 байта за один «выстрел».

Флэш-плеер иногда получает два пакета размером 17520 и 6203, а иногда он получает один пакет из 23723.

РЕДАКТИРОВАТЬ: Кажется, нет способа получить общее количество байтов, связанных с отправкой данных из флэш-памяти. Это очень затруднило бы создание цикла для восстановления «сломанного» пакета.

Я думал, что TCP должен был правильно рекомбинировать пакеты, и у меня возникают трудности с их рекомбинацией.

Это мой обработчик получения во флеше:

var socket:Socket = new Socket();
socket.addEventListener(Event.CONNECT, socketConnectHandler);
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataReceivedHandler);
socket.connect("127.0.0.1", 7445);
socket.writeUTFBytes("hi");

private function socketDataReceivedHandler(event:ProgressEvent):void {
  var socket:Socket = event.target as Socket;
  trace(socket.bytesAvailable);
  var data:ByteArray = new ByteArray();
  socket.readBytes(data);
}

Команда:

trace(socket.bytesAvailable);

будет иногда печатать 23723, а иногда - 17520, а затем 6203. Общий размер приведен только в качестве примера и может быть изменен для каждого отправляющего сокета. Также много сокетов могут быть отправлены или получены одновременно, поэтому разделенные пакеты могут быть смешаны. В c ++ я мог определить общий размер отправленных данных, даже если я еще не получил все отправленные данные.

Ответы [ 2 ]

2 голосов
/ 20 мая 2011

Хорошо ... попробуй и пойми это.TCP Sockets - это не передача пакетов по сети (по крайней мере концептуально), это фактически поток байтов, которые передаются в той же последовательности для получения на другом конце, без сбоев.

Теперь нижнийуровни (IP и т. д.) разбивают поток на пакеты и отправляют его по сети.Стек TCP на принимающей стороне повторно собирает пакеты (при необходимости запрашивает повторные передачи) и снова формирует поток из него, как и когда он продолжает получать пакеты от нижних уровней.Вызов сокета read() в месте назначения извлечет вам байты, которые были получены в потоке до сих пор.Таким образом, вы никогда не можете быть уверены, что один вызов read() соберет вам все отправленные данные.

Хитрость заключается в использовании нескольких вызовов read().У вас может быть два возможных сценария для решения этой проблемы:

(1) Когда вы знаете, сколько именно байтов вы должны получить.Здесь вы просто продолжаете вызывать read(), пока не получите указанное количество байтов.

(2) Когда вы не знаете, сколько байтов вы должны получить.Это довольно сложно.Здесь вы должны выбрать Страж.Итак, в конце отправки вы отправляете все данные, которые вам нужно отправить, а затем отправляете этого Стража.К тому времени, когда я уверен, что вы уже поняли, что на приемном конце вы продолжаете read(), пока не получите Sentinel.

Никогда не думайте о TCP-сокетах как о пакетах.Его легко погрузить, когда вы думаете о них как о потоках.

2 голосов
/ 20 мая 2011

Это не имеет ничего общего с TCP. Сокет может отправить вам любое количество байтов, если он составляет хотя бы один байт. Таким образом, вы можете получить [1, 23722]. Правильный способ сделать это - вызвать read в цикле и заполнить массив самостоятельно. Если ваш код не содержит цикл, но работает, то он работает случайно. Это не может работать без цикла.

Редактировать: не использовать bytesAvailable. Проверьте возвращаемое значение функции чтения. Проверьте свой код: если ваш код основан на bytesAvailable, это неправильно.

Edit2: похоже, flash api (который я не знаю) работает иначе, чем сокет api, который используют все другие фреймворки и языки. Я предполагал, что это будет работать так же, поэтому позвольте мне исправить: у вас должен быть следующий цикл:

int writePos = 0;
var array = ...;
while true:
 wait for bytes to become available. i do not know how to do this but one method would be 'while bytesAvailable == 0 then sleep 10'
 var bytesAvailableCopy = bytesAvailable; //copy because this value can change anytime
 socket.read(array, writePos, bytesAvailableCopy );
 writePos += bytesAvailableCopy;
 if(writePos == maxLength) break;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...