AS3-Flash / AIR Socket Communication 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 2

1 ответ:

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

Security.loadPolicyFile("xmlsocket://192.xx.xx.xx:843");
Если вы посмотрите на журналы вашего сервера, то обнаружите, что при первом подключении к серверу был сделан запрос в виде <policy-file-request/>.
Когда-то это было запрос завершен и файл доставлен клиенту, после чего соединение будет закрыто клиентом всегда.
На стороне клиента, как только кросс-домен получен и соединение закрыто, вы можете снова подключиться и отправить по желанию.


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

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

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 должен вернуть файл crossdomain на этом порту