AS3 - Flash/AIR Socket Communication writeUTFBytes

2019-02-11 02:37发布

问题:

I have a socket server listening on 2 ports, 1 port for the socket server and 1 port for the policy server.

My code is below, in this scenario, data is sent and received perfectly fine. however, for example if I add a button with a simple:

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

after the initial connection, it doesn't seem to send any data to my server (I have my server printing all data transmissions to the console for checking) Initial connections work fine, as seen below:

//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:

You basically have it right you just missed something.
The initial connection is saved for the crossdoamin file even is you specify another port it will try to get the file from 4444 first and if that fails then it will go for the master on the default port(843).
Here is your offending line

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

If you look at your server logs you will find that when the first connection was made there was a request in the form of <policy-file-request/> made to the server.
Once that request is completed and the file delivered to the client then the connection will be closed by the client always.
On the client side once the crossdomain is received and the connection closed you can then reconnect and send at will.


So to recap.
Your flash app made a connection to the server.
Then your app requested the crossdomain and sat and waited
Before the connection timed out you then proceeded to send data of some sort over your the connection
The app still waiting for the cross domain received a response from your server
Since the data received from the server is not the crossdomain.xml file your app closed the connection and will not allow reconnects

I changed your code a bit to auto reconnect
However your server on port 4444 should return the crossdomain file when there is a request for it.

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

Don't forget for this to work your server on port 4444 needs to return the crossdomain file on that port