AS3 - Flash/AIR 套接字通信 writeUTFBytes 只能工作一次

发布于 2024-11-06 18:43:09 字数 1196 浏览 1 评论 0原文

我有一个套接字服务器侦听 2 个端口,其中 1 个端口用于套接字服务器,1 个端口用于策略服务器。

我的代码如下,在这种情况下,数据发送和接收完全正常。但是,例如,如果我添加一个带有简单的按钮:

socket.writeUTFBytes("消息"); socket.flush(); 初始连接后,它

似乎没有向我的服务器发送任何数据(我让我的服务器将所有数据传输打印到控制台进行检查)初始连接工作正常,如下所示

: //首先与套接字服务器进行身份验证: 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();

    }

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

    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

仙女山的月亮 2024-11-13 18:43:09

你基本上是对的,你只是错过了一些东西。
初始连接会保存为 crossdoamin 文件,即使您指定另一个端口,它也会首先尝试从 4444 获取文件,如果失败,那么它将在默认端口 (843) 上获取主服务器。
这是您的违规行

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

如果您查看服务器日志,您会发现当第一次连接时,有一个格式为 的请求发送至服务器。
一旦该请求完成并将文件传递给客户端,则客户端将始终关闭连接。
在客户端,一旦收到跨域并关闭连接,您就可以重新连接并随意发送。

回顾一下。
您的 Flash 应用程序已与服务器建立连接。
然后您的应用程序请求跨域并等待
在连接超时之前,您继续通过连接发送某种数据
仍在等待跨域的应用收到了来自您服务器的响应
由于从服务器收到的数据不是 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 上的服务器正常工作,需要返回该端口上的跨域文件

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文