我有一个多人游戏,它从服务器读取XML数据:
_socket = new Socket();
_socket.addEventListener(ProgressEvent.SOCKET_DATA, handleTcpData);
.....
private function handleTcpData(event:Event):void {
while (_socket.bytesAvailable) {
var str:String = _socket.readUTF();
updateGUI(str);
}
}
在大多数情况下,它可以正常工作,但有时用户会抱怨
游戏为他们挂起。他们能够发送命令
服务器,但从我怀疑他们的描述,该功能
上面对他们不起作用,updateGUI()
停止被调用。
这个问题难以调试......我认为我的服务器(在Perl / C中, 非分叉,使用poll())效果很好,我必须做点什么 在Flash方面是错误的。
在这里拨打readUTF()
是个好主意吗?很可能就是这样
只有部分UTF字符串到达,然后是Flash电影
会冻结readUTF()
,不是吗? (我以前从未见过)
更新
是的,谢谢,我需要抓住EOFError
,我也有很好的建议
在邮件列表中,我必须阅读_socket.bytesAvailable
个字节
进入ByteArray
并使用它(检查我的完整信息
到了) - 其他任何东西都不可靠。
所以我想出了这个,但仍然有一个缺陷:
private function handleTcpData(event:Event):void {
var len:uint;
if (0 == _socket.bytesAvailable)
return;
try {
_socket.readBytes(_ba, _ba.bytesAvailable, _socket.bytesAvailable);
// read the length of the UTF string to follow
while (_ba.bytesAvailable >= 2) {
len = _ba.readUnsignedShort();
// invalid length - reset
if (0 == len) {
trace('XXX invalid len = ' + len);
_ba.position = 0;
_ba.length = 0;
return;
}
if (_ba.bytesAvailable >= len) {
var str:String = _ba.readUTFBytes(len);
updateGUI(str);
// copy the remaining bytes
// (does it work? can it be improved?)
var newBA:ByteArray = new ByteArray();
newBA.readBytes(_ba);
_ba = newBA;
}
}
} catch(e:Error) {
trace('XXX ' + e);
_ba.position = 0;
_ba.length = 0;
return;
}
}
我也想知道,如果复制剩余的字节可能是 改进了(即每次都没有分配新的ByteArray)?
我可以经常重现这个漏洞,幸运的是
答案 0 :(得分:2)
我想,我找到了解决方案。 由于TCP性质,可能存在两个问题:
1)带有前缀的几个UTF字符串一次到达 2)带有前缀的不完整的UTF字符串
此代码应处理:
private function handleTcpData(event:Event):void {
// CASE 1, JUST KEEP EXTRACTING UTF-STRINGS
while(_socket.bytesAvailable) {
try{
var str:String = _socket.readUTF();
updateGUI(str);
}catch(e:Error){
// CASE 2 INCOMPLETE STRING,
// WILL BE READ BY LATER handleTcpData CALL
return;
}
}
}
另外,在我的原始代码中,我正在以错误的方式复制ByteArray。我应该:
var newBA:ByteArray = new ByteArray();
_ba.readBytes(newBA);
_ba = newBA;
甚至可以在不创建newBA的情况下就地执行。
答案 1 :(得分:1)
所有socket.read*
方法都可能会抛出EOFError
和IOError
,因此请务必抓住它们。它可能就是这么简单吗?
另一个想法是,readUTF()
调用假定前两个字节(一个短)应该包含UTF字符串的字节长度。如果您的perl服务器没有发送该长度,则可能是readUTF()
调用将第一个UTF 字符解释为字节长度,因此最终等待更多数据从未到达。
尝试使用:
var str:String = _socket.readUTFBytes(_socket.bytesAvailable);
除此之外,你真的需要能够重现这个问题,或者你很难知道你是否已经修复了它。