Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Считывать из сокета в ByteArray (http://www.flasher.ru/forum/showthread.php?t=136709)

afarber 24.02.2010 03:10

Считывать из сокета в ByteArray
 
Привет,

мой мувик считывает через сокет от сервера (на Перле)
сначала длину UTF строки как unsigned short и потом саму эту строку.

Сначала я пытался делать просто:

Код AS1/AS2:

_socket = new Socket();
_socket.addEventListener(ProgressEvent.SOCKET_DATA, handleTcpData);
 
private function handleTcpData(event:Event):void {
  while (_socket.bytesAvailable) {
    var str:String = _socket.readUTF();
    updateGUI(str);
  }
}

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

Я поискал решения в интернете и похоже что единственный
надежный способ - это читать _socket.bytesAvailable байтов
в отдельный ByteArray и когда видишь, что там достаточно
данных, вычитывать их оттуда нужными методами
(типа readUTF, readShort, readObject и т.д.).

И вот мой новый код:

Код AS1/AS2:

private function handleTcpData(event:Event):void {
      var len:uint;
 
      if (0 == _socket.bytesAvailable)
              return;
 
      try {
              _socket.readBytes(_ba, _ba.bytesAvailable, _socket.bytesAvailable);
 
              // прочитать длину UTF строки
              while (_ba.bytesAvailable >= 2) {
                      len = _ba.readUnsignedShort();
 
                      if (0 == len) {
                              trace('XXX invalid len = ' + len);
                              _ba.position = 0;
                              _ba.length = 0;
                              return;
                      }
 
                      // теперь прочитать саму UTF строку
                      if (_ba.bytesAvailable >= len) {
                              var str:String = _ba.readUTFBytes(len);
                              updateGUI(str);
 
                              // скопировать оставшиеся байты (не работает)
                              var newBA:ByteArray = new ByteArray();
                              newBA.readBytes(_ba);
                              _ba = newBA;
                      }
              }
      } catch(e:Error) {
              trace('XXX ' + e);
              _ba.position = 0;
              _ba.length = 0;
              return;
      }
}

К сожалению этот код не работает когда через сокет
приходят например сразу 2 строки с префиксами.

Я добавил пару trace() и вижу что не работает мой код,
в котором я пытаюсь убрать из ByteArray те байты,
которые я уже обработал:

Код AS1/AS2:

                               // скопировать оставшиеся байты (не работает)
                              var newBA:ByteArray = new ByteArray();
                              // здесь newBA.length почему-то 0
                              newBA.readBytes(_ba);
                              _ba = newBA;

Подскажите как мне исправить?

Т.е.: если в ByteArray две UTF-строки с префиксами
и первую строку я обработал, то как мне ее убрать оттуда?

Спасибо
Алекс

wvxvw 24.02.2010 03:45

Код AS3:

private function handleTcpData(event:Event):void
{
        var len:uint;
        var str:String;
        var newBA:ByteArray;
 
        if (!_socket.bytesAvailable) return;
        try
        {
                _socket.readBytes(_ba, _ba.bytesAvailable, _socket.bytesAvailable);
 
                // прочитать длину UTF строки
                while (_ba.bytesAvailable >= 2)
                {
                        len = _ba.readUnsignedShort();
                        if (!len)
                        {
                                trace("XXX invalid len = " + len);
                                _ba.position = 0;
                                _ba.length = 0;
                                return;
                        }
                        // теперь прочитать саму UTF строку
                        if (_ba.bytesAvailable >= len)
                        {
                                str = _ba.readUTFBytes(len);
                                updateGUI(str);
 
                                // скопировать оставшиеся байты (не работает)
                                newBA = new ByteArray();
                                if (_ba.bytesAvailable)
                                        newBA.readBytes(_ba, 0, _ba.bytesAvailable);
                                _ba = newBA;
                        }
                        else
                        {
                                // Ну вот вы и не прочитали неокончившуюся строку, а что теперь?
                        }
                }
        }
        catch (e:Error)
        {
                trace('XXX ' + e);
                _ba.position = 0;
                _ba.length = 0;
                return;
        }
}


afarber 24.02.2010 11:43

Нашел ответ, я копировал байты не в ту сторону, надо так:

Код AS1/AS2:

var newBA:ByteArray = new ByteArray();
_ba.readBytes(newBA);
_ba = newBA;

Цитата:

// Ну вот вы и не прочитали неокончившуюся строку, а что теперь?
Не проблема, когда придет остаток строки, handleTcpData() вызовется 2й раз

пока
Алекс

etc 24.02.2010 22:54

Не забывайте, что данные могут прийти не полностью за один проход.

cleptoman 24.02.2010 23:02

а почему могут прийти не полностью?
(вопрос тож актуален)

mayakwd 24.02.2010 23:03

потому что сокеты пхп например разрезают информацию в случае заполнения буффера отправки.

wvxvw 24.02.2010 23:14

Цитата:

Сообщение от afarber (Сообщение 888832)
Не проблема, когда придет остаток строки, handleTcpData() вызовется 2й раз

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

etc 24.02.2010 23:32

Цитата:

Сообщение от cleptoman (Сообщение 889049)
а почему могут прийти не полностью?
(вопрос тож актуален)

Есть такая штука, называется «пакеты». Размер оного регламентируется настройками сети и прочими параметрами. Так вот входящий поток будет разбит на эти пакеты.


Часовой пояс GMT +4, время: 18:59.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.