解決AS3 Socket編程中最令人頭疼的問題

什麼是最令人頭疼的問題?也許大家會異口同聲的說:“安全問題”,不錯,不僅僅是AS3 的Socket,整個AS3語言中最令人頭疼的問題也無非就是安全問題了。

很 多同行的兄弟在鬱悶的時候就會罵Adobe。但是,罵歸罵,問題終歸是要解決的,Adobe做這樣的限制肯定是有他的用意的,大家都知道,swf文件是很 容易被反編的,那麼也就是說你的swf文件內部與服務器通信的方式及路徑是很容易被別人發現的,如果你的服務器中沒有任何訪問限制,那麼你的服務器很容易 被一些人攻破,這並不需要很高的水平,只要一直刷,你的服務器就完了。

兄弟,您罵夠了嗎?我們來解決問題吧?

用Java寫完Socket服務器後,運行,一切正常,用Flex寫全Socket客戶端後,運行,一切正常,可是當把生成的swf文件拷到其它地方來運行就出錯了,總是無法連接服務器,然後就開始拋securityError,下面我們看一下輸出信息。

打 開Flash CS3,打開遠程調試器,選擇菜單如 Debug->Begin Remote Debug Session->ActionScript3.0(中文版選擇菜單如:調試->開始 遠程調試會話->ActionScript3.0),下面我們打開客戶端swf文件(記得此文件一定是調試版swf),則它會自動連接Flash CS3 的調試器,在Flash CS3中輸出相關的調試信息。

可以看到輸出信息如下:

------------------------------------

[SWF] C:\Users\Administrator\Desktop\MyClientFlash.swf - 1112717 bytes after decompression

警告: [strict] 將忽略 xmlsocket://localhost:9999 處的策略文件,因爲出現語法錯誤。請訪問 http://www.adobe.com/go/strict_policy_files_cn 以解決此問題。

*** 安全沙箱衝突 ***

到 localhost:9999 的連接已停止 - 不允許從 file:///C|/Users/Administrator/Desktop/MyClientFlash.swf 進行連接

錯誤: 拒絕請求位於 xmlsocket://localhost:9999 的資源(請求者從 file:///C|/Users/Administrator/Desktop/MyClientFlash.swf 發出請求),原因是缺乏策略文件權限。

------------------------------------

原因是沒有在服務器的9999端口放置安全策略文件(我寫的服務器用的是9999端口),那麼好吧,我就在此處給客戶端返回了一個安全策略文件信息,此文件格式如下:

<?xml version="1.0"?>

<cross-domain-policy>

    <site-control permitted-cross-domain-policies="all"/>

    <allow-access-from domain="localhost" to-ports="9999,300-400" />

</cross-domain-policy>

上述示例中是允許來自localhost域的swf文件訪問9999端口和300至400端口,你也可以用*來代替localhost以允許來自任何域的swf文件訪問。

此時我將客戶端文件請求的信息在Java中打印出來,看到的是一段包含<policy-file-request/>的字符串,當Java服務器接收到這個字符串時,立即返回安全策略文件字符串。

我想這樣應該沒什麼問題了吧,可是當我再連接服務器時仍然無法連接,輸出信息成了這樣:

-------------------------------------

[SWF] C:\Users\Administrator\Desktop\MyClientFlash.swf - 1112717 bytes after decompression

警告: 等待 socket 策略文件時在 xmlsocket://localhost:9999 上超時(3 秒鐘)。這不會造成任何問題,但可訪問 http://www.adobe.com/go/strict_policy_files_cn 以獲得說明。

*** 安全沙箱衝突 ***

到 localhost:9999 的連接已停止 - 不允許從 file:///C|/Users/Administrator/Desktop/MyClientFlash.swf 進行連接

錯誤: 拒絕請求位於 xmlsocket://localhost:9999 的資源(請求者從 file:///C|/Users/Administrator/Desktop/MyClientFlash.swf 發出請求),原因是缺乏策略文件權限。

-------------------------------------

這時我並不灰心,就按照它的說明去了http://www.adobe.com/go/strict_policy_files_cn這裏查看說明了。

等我看到這個頁面時,我真的鬱悶了,上面全是亂說一通,根本不着邊,全是一些沒用的信息,虧Adobe想得出來提示我到這裏看。

就 在我將要放棄解決這個問題的時候,我發現了另外一個現象,那就是當我剛開始連接服務器時,服務器端並沒有打印出來客戶端的請求信息 (<policy-file-request/>),而是在Flash CS3的調試器輸出了超時錯誤之後,服務器端纔打印出來這個請求信 息。

這時我看到了一線希望,那就是服務器端確實出現了等待,這肯定是服務器端的程序問題。服務器端接收請求的處理代碼片斷如下:

BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));

if(br.readLine().indexOf("<policy-file-request/>")!=-1){

//開始返回授權文件信息

...

}

其中變量s是ServerSocket實例通過accept方法獲得的Socket實例。

此時我開始懷疑是readLine方法的問題了,因爲readLine方法是當程序讀到\n或者\r時纔會返回信息,所以肯定是此方法中出現了等待,因爲起初客戶端並沒有傳來換行符或者回車符。

於是我改變了讀取字符串的方法,不再用readLine了,而取流中前22個字符,代碼片斷如下所示:

BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));

char[] ch=new char[22];

br.read(ch, 0, ch.length);

StringBuffer sb=new StringBuffer();

for(int i=0;i< ch.length;i++){

sb.append(ch[i]);

}

String st=sb.toString();

if(st.indexOf("<policy-file-request/>")!=-1){

//開始返回授權文件信息

...

}

當我再連接服務器時,果然不出我所料,成功連接服務器。

但是連接過程有點慢,貌似此過程也正好是3秒鐘,莫非在連接此服務器之前已經進行了另外一次連接,而且是失敗的。

查看Adobe官網的資料才明白,flashplayer會在連接指定的端口之前連接目標主機的843端口,如果3秒後得不到授權文件纔再向指定的端口去請求授權文件,如果再經過3秒還得不到授權文件的話,則斷開連接,拋出securityError。

那 意思就是說在連接我的服務器的9999端口之前還連接了我的服務器的843端口,並且在843端口等待了3秒,沒有得到授權文件,之後開始向我指定的端口 請求此授權文件。那好吧,既然你要了,我就給你吧,不給你的話你還再磨磯磨磯,於是我又在843端口開了一個ServerSocket,此處專門處理授權 文件的請求。

這時我再連接服務器,呵呵,特快專列(T843),立即就連接上了。

說明:貌似有很多客戶機上的843端被禁用了,所以爲了保險,需要在指定端口和843端都要能夠處理授權文件的請求。

=======================

原作者:粉色男孩http://hi.baidu.com/fsnhf

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章