AS3 - связь через разъем Flash/AIR writeUTFBytes работает только один раз

У меня есть сервер сокетов, прослушивающий 2 порта, 1 порт для сервера сокетов и 1 порт для сервера политик.

Мой код ниже, в этом случае данные отправляются и получаются в полном порядке. однако, например, если я добавлю кнопку с простым:

socket.writeUTFBytes("Message"); socket.flush();

после первоначального подключения он, похоже, не отправляет никаких данных на мой сервер (мой сервер распечатывает все передачи данных на консоль для проверки). Первоначальные подключения работают нормально, как показано ниже:

//authenticate with socket server first: var xmlSocket = new XMLSocket(); xmlSocket.connect("192.xx.xx.xx", 843);

try {
    Security.loadPolicyFile("xmlsocket://192.xx.xx.xx:843");
} catch (e:IOError) {
    //tbOutput.text += e.text;
}


var socket:Socket = new Socket();
socket.addEventListener(Event.CONNECT, onConnect);
socket.addEventListener(Event.CLOSE, onClose);
socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecError);

try {
socket.connect("192.xx.xx.xx", 4444);
} catch (e:IOError) {
    //error traced
}


function onConnect(e:Event):void {
    //initial message to socket server:
    var Message:String;
    //message contains something
    socket.writeUTFBytes(Message.toString() + "<EOF>");
    socket.flush();

    }

1 ответ

Решение

В принципе, ты прав, просто что-то пропустил.
Первоначальное соединение сохраняется для файла кроссдозамины, даже если вы укажете другой порт, он сначала попытается получить файл с 4444, а в случае неудачи он перейдет к мастеру на порту по умолчанию (843).
Вот твоя оскорбительная линия

Security.loadPolicyFile("xmlsocket://192.xx.xx.xx:843");

Если вы посмотрите журналы вашего сервера, то обнаружите, что при первом подключении был запрос в виде <policy-file-request/> сделал на сервер.
Как только этот запрос будет выполнен и файл доставлен клиенту, клиент всегда будет закрывать соединение.
На стороне клиента после получения междомена и закрытия соединения вы можете затем повторно подключиться и отправить по желанию.


Итак, подведем итоги.
Ваше флэш-приложение установило соединение с сервером.
Тогда ваше приложение запросило междоменный домен и сидел и ждал
До истечения времени ожидания соединения вы продолжали посылать какие-либо данные через ваше соединение
Приложение, все еще ожидающее междоменный домен, получило ответ от вашего сервера.
Поскольку данные, полученные с сервера, не являются файлом crossdomain.xml, ваше приложение закрыло соединение и не разрешит повторное соединение

Я немного изменил ваш код для автоматического переподключения
Однако ваш сервер на порту 4444 должен возвращать файл междомена, когда есть запрос на него.

try {
  Security.allowDomain('192.xx.xx.xx');
  Security.loadPolicyFile("xmlsocket://192.xx.xx.xx:4444");
} catch (e:IOError) {
    //tbOutput.text += e.text;
}


var socket:Socket = new Socket();
socket.addEventListener(Event.CONNECT, onConnect);
socket.addEventListener(Event.CLOSE, onClose);
socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecError);

function connect( ){
  if( !socket.connected ){
    try {
      socket.connect("192.xx.xx.xx", 4444);
    } catch (e:IOError) {
      //error traced
    }
  }
}

function onConnect(e:Event):void {
    //initial message to socket server:
    var Message:String;
    //message contains something
    //socket.writeUTFBytes(Message.toString() + "<EOF>");// EOF bad
    socket.writeUTFBytes(Message.toString() + String.fromCharCode(0) ); // NULL good
    socket.flush();

}

function onResponse(e:ProgressEvent):void {
  var read:String = this.readUTFBytes(this.bytesAvailable );

  // I test for a < since my server will never return a "<" as the first character
  // unless it is the crossdomain.xml file
  // you may need to change this for your needs
  if( read.charAt(0) !='<' ){
    if( read ){
      // so something with your response
    }
  }else{
    // recieved crossdomain policy nothing to really do here it is handled internally
  }
}


var connectTimer:Timer = new Timer( 1000 );
connectTimer.addEventListener(TimerEvent.TIMER, connect );
connectTimer.start();

Не забудьте, что для работы вашего сервера через порт 4444 необходимо вернуть файл междомена на этот порт

Другие вопросы по тегам