AS3 не может декодировать объект AMF3 из сокета, отправленного Java

У меня есть сервер сокетов java, который отправляет объект Animal клиенту Flash при подключении. Объект отправляется так:

Amf3Output amf3Output = new Amf3Output(SerializationContext.getSerializationContext());
amf3Output.setOutputStream(userSocket.getOutputStream());
amf3Output.writeObject(animal);

И код на стороне флешки:

var object:Object = socket.readObject();
trace(object);
trace(object as Animal);

Однако, когда вторая трассировка дает мне null

Я проверил, что java отправляет 31 байт, а Flash получает 31 байт.

Я думаю, что мои классы Java и AS3 могут не соответствовать некоторым требованиям AMF.

Java-класс:

package main;

public class Animal {

   public String name;
   public int age;
}

Класс AS3:

package  
{

    [Bindable]
    [RemoteClass(alias="main.Animal")]
    public class Animal 
    {
        public var name:String;
        public var age:int;

    }

}

person Rob Fox    schedule 04.07.2011    source источник
comment
Вы используете шлюз AMF, например LiveCycle или BlazeDS? Если да, то какой.   -  person JeffryHouser    schedule 04.07.2011
comment
Я не уверен, что вы имеете в виду под шлюзом AMF, но я просто взял файлы flex-messaging-core.jar и flex-messaging-common.jar из папки blazeDS lib, поскольку они используются для процесса кодирования/декодирования.   -  person Rob Fox    schedule 04.07.2011
comment
Шлюз AMF — это, по сути, некоторая программа, которую вы запускаете на сервере, которая преобразует объекты на стороне сервера в объекты на стороне клиента, а объекты на стороне клиента — в объекты на стороне сервера. Он также обрабатывает маршрутизацию ваших вызовов RemoteObject. Вероятно, он делает и другие вещи. Похоже, вы пытаетесь использовать классы BlazeDS вручную; в отличие от настройки BlazeDS в качестве шлюза и предоставления ему возможности справиться с этим. Это необычный подход.   -  person JeffryHouser    schedule 04.07.2011
comment
Я использую сокеты и передаю данные с помощью потоков сокетов. Я не понимаю, почему это не сработает, если я использую кодировщик BlazeDS. Я также знаю, что есть и другие фреймворки, которые делают это.   -  person Rob Fox    schedule 04.07.2011
comment
Я тоже не знаю, почему он не работает. Вы используете очень необычный подход к использованию AMF. Я уверен, что в конце концов это даст вам четкое представление о протоколе и о том, как он реализован, но я не знаю, как ответить на ваш вопрос. Удачи!   -  person JeffryHouser    schedule 04.07.2011
comment
@www.Flextras.com Необходимо использовать шлюз AMF? Я пробовал отправить строку или int клиенту, все работает хорошо. Но мне не удалось отправить пользовательский объект клиенту   -  person jason    schedule 12.12.2011


Ответы (3)


Я не знаком с Java и доступными для нее сериализаторами/десериализаторами AMF, но отправка типизированных объектов через сокеты действительно поддерживается во флэш-памяти и работает правильно, если вы отправляете правильные данные. Ниже приведен пример сервера сокетов в ruby, взаимодействующего с приложением Flash. Я использую RocketAMF для отправки объекта AMF3 через сокет клиенту после его подключения.

SocketTest.as:

package {
    import flash.display.Sprite;
    import flash.net.registerClassAlias;
    import org.rackAMF.*;
    import flash.net.Socket;
    import flash.events.*;

    public class SocketTest extends Sprite {
        private var socket:Socket;

        public function SocketTest() {
            registerClassAlias('Animal', Animal);

            socket = new Socket();
            socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
            socket.connect("localhost", 8081);
        }

        private function onResponse(e:ProgressEvent):void {
            var animal:Animal = socket.readObject() as Animal;
            trace(Object(animal).constructor); // [trace] [class Animal]
            trace(animal.name); // [trace] Zebra
            trace(animal.age); // [trace] 5
        }
    }
}

class Animal {
    public var name:String;
    public var age:int;
}

socket_server.rb:

require 'rubygems'
require 'socket'
require 'rocketamf'

class Animal
  attr_accessor :name, :age
end

# Map "Animal" in ruby to "Animal" in flash
RocketAMF::ClassMapper.define do |m|
  m.map :as => 'Animal', :ruby => 'Animal'
end

server = TCPServer.open(8081)
loop {
  client = server.accept

  animal = Animal.new
  animal.name = "Zebra"
  animal.age = 5
  client.write RocketAMF.serialize(animal, 3)

  client.close
}
person warhammerkid    schedule 06.07.2011
comment
Теперь я не уверен, неправильно ли я сопоставил классы AS3 и Java или var animal:Animal = socket.readObject(), поскольку Animal сделал свою работу, но она работает! Спасибо :). - person Rob Fox; 07.07.2011
comment
@ Роб Фокс, кажется, я знаю, почему метаданные не работали. Не могу поверить, что забыл об этом. Это «проблема» с вашим процессом компиляции. Вероятно, у вас нет переменной класса, которая указывает «Животное», поэтому компилятор flex не будет компилировать этот класс и не будет знать о метаданных. Сохраните свои метаданные там и внутри класса, называемого сокетом, создайте private var animal:Animal;, и он должен работать. - person J_A_X; 07.07.2011
comment
Я действительно этого не сделал, и, поскольку я назвал его внутренним классом, компилятор скомпилировал его. Интересный. - person Rob Fox; 07.07.2011

Вы проверили, что objectEncoding установлено на 3 на стороне ActionScript? Если вы отправляете данные AMF3, а он пытается прочитать данные AMF0, это не сработает.

person warhammerkid    schedule 04.07.2011
comment
у меня нет. ASDoc говорит, что это по умолчанию. Я попробую и вернусь. - person Rob Fox; 04.07.2011
comment
Да, я проверил, и для кодировки объекта установлено значение 3. - person Rob Fox; 05.07.2011

Так как вы взяли части BlazeDS, трудно определить, каковы требования AMF3 по сравнению с требованиями BlazeDS. Что я скажу, так это то, что BlazeDS нужны классы Java, которые следуют спецификации Java Beans, а это означает соответствие геттеров и сеттеров.

Я также предполагаю, что на стороне Flex требуется больше для десериализации полезной нагрузки AMF3: сетевой формат не является объектом Actionscript 3.0. Я сделал некоторую пользовательскую сериализацию BlazeDS, поэтому я думаю, что вы что-то упускаете на стороне Flex.

Есть ли причина, по которой вы не используете BlazeDS (или GraniteDS) для связи?

person SteveD    schedule 05.07.2011
comment
Мне нужно быстрое соединение с высоким трафиком на основе сокетов. Мне сказали, что BlazeDS не идеален для этого. - person Rob Fox; 05.07.2011