2010-02-23 18 views
1

我有一個多人遊戲,它從服務器讀取XML數據:信息bytesAvailable,的readUTF()和ProgressEvent.SOCKET_DATA

_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(),不是嗎? (我從來沒有見過,雖然)

UPDATE:

是的,謝謝,我需要趕上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; 
     } 
} 
  • 當有太多可用的字節數,例如800 和我的消息只有400個字節長,然後它Stucks。

另外我想知道,如果複製剩餘的字節可能是 改進(即沒有每次分配一個新的ByteArray)?

我經常可以重現這個漏洞,幸好

回答

2

我想,我找到了解決方案。 由於TCP的性質可以有2問題的案例:

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

所有socket.read*方法可能拋出EOFErrorIOError,所以一定要確保你趕上他們。它可能是這樣簡單的事情?

另一個想法是,readUTF()調用假定前兩個字節(一個短)應該包含UTF字符串的字節長度。如果您的perl服務器未發送該長度,則可能是由於readUTF()調用將第一個UTF 字符解釋爲字節長度,因此最終會等待更多永遠不會到達的數據。

嘗試使用:

var str:String = _socket.readUTFBytes(_socket.bytesAvailable); 

其他,你真正需要的是能夠重現問題,或者它是相當不可能知道,如果你有固定的。

+0

是的,謝謝,我的Perl服務器發送的前綴長度,這不是一個問題。 – 2010-02-23 21:39:38