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();

    }


person MWard    schedule 12.05.2011    source източник


Отговори (1)


По принцип сте прави, просто сте пропуснали нещо.
Първоначалната връзка се запазва за файла crossdoamin, дори ако посочите друг порт, той първо ще се опита да вземе файла от 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 трябва да върне файла на кръстосания домейн на този порт

person The_asMan    schedule 12.05.2011
comment
Съжалявам за забавянето в отговора на тази помощ, проектът се влоши няколко пъти и трябваше да изчакам, докато се върна към него!. Оттогава преместих заявката за междудомейн в главния порт и я обработих така: pastebin.com/J33Mzk1q Това е малко объркано, но просто искам да видя нещата работещи! Все още имам първоначалния проблем, моето флаш приложение може да изпраща и получава данни веднъж, но всяко друго socket.writeUTFBytes(Message); socket.flush(); нищо не се записва на сървъра - person MWard; 20.09.2011
comment
На вашия сървър в ReadCallBack не обработвате (!bytesRead › 0) Това е мястото, където клиентът прекъсва връзката. Опитайте да поставите код за отстраняване на грешки там и ще видите, че се задейства. - person The_asMan; 20.09.2011
comment
променете ‹EOF› на String.fromCharCode(0) сървърът ще чете, докато не види нулев знак или докато буферът се напълни. Така че, ако предавате големи количества данни, трябва да зациклите четенето. - person The_asMan; 20.09.2011
comment
какво трябва да поставя в условието (!bytesRead › 0)? По принцип искам да подготвя сървъра за всякакви други входящи данни? - person MWard; 20.09.2011
comment
The_asMan, много ти благодаря, че спомена ‹EOF›, имах проблем в моя експеримент и точно това ми липсваше! :) - person bigp; 07.03.2013
comment
Въпреки че порт 4444 се използва широко в примери, той се оказа лош избор в природата за нас, тъй като се сблъсква с уеб проксита за потребители на определени интернет доставчици. Използването на номера на портове 49152–65535 е по-надеждно. - person Dave Walker; 15.07.2013