<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    瘋狂

    STANDING ON THE SHOULDERS OF GIANTS
    posts - 481, comments - 486, trackbacks - 0, articles - 1
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    Flex通信-與Java實現Socket通信實例

    Posted on 2011-10-09 17:28 瘋狂 閱讀(3891) 評論(0)  編輯  收藏 所屬分類: flex

    Flex通信-與Java實現Socket通信實例  轉自:http://blessht.iteye.com/blog/1136888

    • 環境準備
    【服務器端】
    JDK1.6,“java.net”包對網絡編程提供了非常全面的支持,包括Socket
    開發環境:Eclipse
    【客戶端】
    Flex4,”flash.net”包也提供了Socket的支持
    開發環境:FlashBuilder4

    • 實例效果
    我是用Java啟動一個ServerSocket作為服務器,Flex創建一個頁面,當點擊頁面上的按鈕時向Java服務器發送消息。

    Flex客戶端輸入“阿里巴巴”再點擊按鈕:

     Java控制臺:


     

    • 注意事項
    Flex項目分為兩種:一種是普通的本地項目,也就是不依賴其它服務器;另一種是遠程服務器項目,這需要依賴其它語言的服務器容器。如果是普通的本地項目,Socket通信是非常容易的,但是如果是遠程項目,Socket通信需要考慮Flex安全沙箱問題,后面會詳細介紹。


     

    • Java Socket服務器
    編寫Socket Server代碼的步驟通常是:
    ①創建ServerSocket,定義服務端口號
    ②使用ServerSocket.accept()監聽socket請求,如果有請求會創建一個Socket對象
    ③通過socket.getInputStream()獲取客戶端的請求數據
    ④通過socket.getOutputStream()向客戶端返回數據
    ⑤通過socket.close()結束本次會話
    按照上面的步驟,如果有多個客戶端向服務器發送請求的話,服務器只會處理第一個請求,其它請求會排隊等待,只有第一個請求執行socket.close的時候下一個客戶端請求才會運行。為了實現多客戶端并發請求,在第②步后面需要建立多線程。

    廢話不多說,直接代碼說明。

    首先創建一個SocketUtil類,用于創建ServerSocket和獲取Socket
    Java代碼  
    1. public class SocketUtil {   
    2.        
    3.     /**  
    4.      * 創建ServerSocket  
    5.      * @param port  
    6.      * @return  
    7.      */  
    8.     public static ServerSocket getServerSocket(int port){   
    9.         ServerSocket server = null;   
    10.         try {   
    11.             server = new ServerSocket(port);   
    12.             System.out.println("------ServerSocket創建成功,Port:"+port);   
    13.             return server;   
    14.         } catch (IOException e) {   
    15.             if(server!=null && !server.isClosed()){   
    16.                 try {   
    17.                     server.close();   
    18.                 } catch (IOException e1) {   
    19.                     e1.printStackTrace();   
    20.                 }   
    21.             }   
    22.             throw new RuntimeException("創建ServerSocket時發生異常,Port:"+port,e);   
    23.         }   
    24.     }   
    25.        
    26.     /**  
    27.      * 獲取Socket  
    28.      * @param server  
    29.      * @return  
    30.      */  
    31.     public static Socket getSocket(ServerSocket server){   
    32.         Socket socket = null;   
    33.         try {   
    34.             socket = server.accept();   
    35.             System.out.println("------Socket連接成功,IP:"+socket.getInetAddress());   
    36.             return socket;   
    37.         } catch (IOException e) {   
    38.             if(socket!=null && !socket.isClosed()){   
    39.                 try {   
    40.                     socket.close();   
    41.                 } catch (IOException e1) {   
    42.                     e1.printStackTrace();   
    43.                 }   
    44.             }   
    45.             throw new RuntimeException("創建Socket時發送異常",e);   
    46.         }   
    47.     }   
    48.        
    49. }  
     
    然后創建一個帶多線程的類,用于服務器與客戶端的IO通信
    Java代碼  
    1. public class SocketThread implements Runnable {   
    2.     private Socket socket;   
    3.     private String encoding;   
    4.        
    5.     public SocketThread(Socket socket,String encoding) {   
    6.         this.socket = socket;   
    7.         this.encoding = encoding;   
    8.     }   
    9.        
    10.     /**  
    11.      * 與客戶端交互代碼  
    12.      */  
    13.     @Override  
    14.     public void run() {   
    15.         try {   
    16.             BufferedReader br = new BufferedReader(new InputStreamReader(socket   
    17.                     .getInputStream(), encoding));   
    18.             BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(   
    19.                     socket.getOutputStream(), encoding));   
    20.                
    21.             String getMsg;   
    22.             while ((getMsg = br.readLine()) != null && !"exit".equalsIgnoreCase(getMsg)) {   
    23.                 // 客戶端未提出"exit"命令,則循環交流   
    24.                 System.out.println("From client message:" + getMsg);   
    25.                 bw.append("你好[" + socket.getInetAddress() + "],服務器收到你的信息:"  
    26.                         + getMsg + "\r\n");   
    27.                 bw.flush();   
    28.             }   
    29.                
    30.             //客戶端提出"exit"請求,關閉當前socket...   
    31.             br.close();   
    32.             bw.close();   
    33.             socket.close();   
    34.             System.out.println("當前Socket連接結束......");   
    35.         } catch (Exception e) {   
    36.             if(!socket.isClosed()){   
    37.                 try {   
    38.                     socket.close();   
    39.                 } catch (IOException e1) {   
    40.                     e1.printStackTrace();   
    41.                 }   
    42.             }   
    43.             throw new RuntimeException("Socket線程類發送異常...",e);   
    44.         }   
    45.     }   
    46. }  
     
    最后在Main函數中啟動Socket服務即可:
    Java代碼  
    1. public static void main(String[] args) {   
    2.         new SocketServer().startSocket();   
    3.     }  
     
    • Flex客戶端代碼
    Flex端創建Socket有兩種方式:
    第一種通過connect方法連接Socket服務器:
    Java代碼 復制代碼 收藏代碼
    1. var socket:Socket = new Socket();   
    2. socket.connect("localhost",10086);  
     第二種通過創建Socket實例時在構造函數中傳入服務器ip和端口號連接:
    Java代碼  
    1. socket = new Socket("localhost",10086);  
     Flex通過ByteArray傳送IO數據,這里有一點稍微注意一下在寫入的內容后面會加"\r\n"回車換行符,因為java端是通過BufferedReader.readLine的形式獲取一行數據,如果不換行服務器端IO就一直處于阻塞狀態:
    Java代碼  
    1. //ByteArray存放數據   
    2. var message:ByteArray = new ByteArray();   
    3. //使用UTF形式防止中文亂碼   
    4. message.writeUTFBytes(txt_socket.text+"\r\n");   
    5. //數據寫入緩沖區   
    6. socket.writeBytes(message);  
     Flex有多種事件用于監聽Socket的狀態:
    Java代碼  
    1. Event.CONNECT:Socket與服務器成功連接時觸發的事件   
    2. Event.CLOSE:Socket與服務器斷開連接時觸發的事件   
    3. IOErrorEvent.IO_ERROR:Socket通信時發生IO錯誤時觸發的事件   
    4. ProgressEvent.SOCKET_DATA:服務器返回數據時觸發的事件  

    新建一個Flex普通項目,入口文件定義為index.mxml,在mxml文件中新建一個textinput文本框用于獲取用戶輸入的內容,button按鈕用戶發送內容到java socket服務器,一個label用戶顯示向前socket狀態,另一個label用于顯示從服務器返回的信息。 index.mxml代碼如下:
    Xml代碼  
    1. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"    
    2.                xmlns:s="library://ns.adobe.com/flex/spark"    
    3.                xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">  
    4.   
    5.     <fx:Script>  
    6.         <![CDATA[  
    7.               
    8.               
    9.             private var socket:Socket = null;  
    10.             protected function button1_clickHandler(event:MouseEvent):void  
    11.             {  
    12.                 if(socket==null || !socket.connected){  
    13.                     //連接服務器(ip,port)  
    14.                     socket = new Socket("localhost",10086);  
    15.                       
    16.                     //成功連接狀態事件  
    17.                     socket.addEventListener(Event.CONNECT,function connFun(e:Event):void{  
    18.                         l_status.text = "Connect to server success...";  
    19.                     });  
    20.                     //連接中斷事件  
    21.                     socket.addEventListener(Event.CLOSE,function closeFun(e:Event):void{  
    22.                         l_status.text = "Connect to server closed...";  
    23.                     });  
    24.                     //連接異常事件  
    25.                     socket.addEventListener(IOErrorEvent.IO_ERROR,function closeFun(e:IOErrorEvent):void{  
    26.                         l_status.text = "Connect exception ..."+e.toString();  
    27.                     });  
    28.                     //服務器信息事件  
    29.                     socket.addEventListener(ProgressEvent.SOCKET_DATA,function dataFun(e:ProgressEvent):void{  
    30.                         var getMsg:ByteArray = new ByteArray;  
    31.                         socket.readBytes(getMsg);  
    32.                         l_result.text = getMsg.toString();  
    33.                     });  
    34.                 }  
    35.                   
    36.                 //ByteArray存放數據  
    37.                 var message:ByteArray = new ByteArray();  
    38.                 //使用UTF形式防止中文亂碼  
    39.                 message.writeUTFBytes(txt_socket.text+"\r\n");  
    40.                 //數據寫入緩沖區  
    41.                 socket.writeBytes(message);  
    42.                 //將緩沖區數據發送出去  
    43.                 socket.flush();  
    44.                 //清空文本框內容  
    45.                 txt_socket.text = "";  
    46.             }  
    47.         ]]>  
    48.     </fx:Script>  
    49.   
    50.     <fx:Declarations>  
    51.         <!-- 將非可視元素(例如服務、值對象)放在此處 -->  
    52.     </fx:Declarations>  
    53.     <s:Button x="156" y="56" label="按鈕" click="button1_clickHandler(event)"/>  
    54.     <s:TextInput x="20" y="56" id="txt_socket"/>  
    55.     <s:Label x="20" y="104" id="l_status"/>  
    56.     <s:Label x="234" y="65" id="l_result"/>  
    57. </s:Application>  
     
    代碼編寫完成后運行index.mxml文件,最后執行效果就如前面【實例效果】所示。


    • 安全沙箱
    下面這段是從網上抄的:
    ----------------------------------------------------------------------------
    在 Adobe Flash Player 升級到 9.0.124 后,由于安全策略更改,原來 Socket 或 XmlSocket 的應用里的 http 方式加載安全策略的手段不能繼續使用。更改如下:
    1, 首先檢測目標服務器的 843 端口是否提供安全策略
     

    2, 如果 1 沒有檢測到策略,則檢測 actionscript 是否使用了 Security.loadPolicyFile(xmlsocket://)手段提供安全策略,如果還沒檢測到,則使用第 3 步檢測
    3, 檢測目標服務器目標端口是否提供安全策略。

    在說具體處理方式前,我先描述一下 Flash Player 的驗證過程。在 Flex 程序發出 Socket 或 XmlSocket( 以下統稱為 Socket) 請求前, FlashPlayer 會先判斷是否為本地調用,如果不是。即用一個 Socket 去鏈接到你的服務端,三次握手成功后一方面發出字符串“ <policy-file-request/>\0 “另一方面監聽返回的安全策略。安全策略接收成功后, FlashPlayer 就斷開驗證的 Socket ,然后再運行程序本身的 Socket 。在整個 SWF 運行期間,無論你請求多少次,只要域相同, FlashPlayer 就只驗證一次。這里有兩個重點:
     
    第一個是驗證的 Socket 和程序的 Socket 是兩個 Socket 。所以你在本地測試時,服務端監聽到 N 個 Socket 請求,但布置到服務端后,服務端會監聽到 N+1 個請求。
    第二是驗證的 Socket 發送“ <policy-file-request/>\0 “請求和接收你的策略文件是沒有先后關系的,所以你沒必要接收完“ <policy-file-request/>\0 “后才發策略文件。我的做法是只要監聽到請求,就把策略字符串發過去。
    -----------------------------------------------------------------------------------

    那么簡單的說,如果Flex項目依賴其它語言的服務器的話(比如依賴J2EE服務器),在flex的socket客戶端向JavaSocket服務器發送請求之前,Flex會優先發送一個安全驗證消息,如果java服務器不返回驗證消息則當前socket通信失敗。
    解決辦法有很多種,我在網上也看了很多,但是很多寫得有問題。
    根據我多方調查,個人覺得這種方案比較靠譜:
    在Java服務器端創建一個端口號為843的ServerSocket監聽Flex安全沙箱驗證消息,如果接收到<policy-file-request/>文件信息,則向客戶端返回XMl驗證內容:“<?xml version=\"1.0\"?><cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0”
    具體代碼如下:
    Java代碼  
    1. /**  
    2.  * 處理與Flex認證的線程類  
    3.  * @author Administrator  
    4.  */  
    5. public class PolicyThread implements Runnable {   
    6.     private final String policy_xml = "<policy-file-request/>";   
    7.     private final String cross_xml = "<?xml version=\"1.0\"?><cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0";   
    8.     private Socket socket;   
    9.        
    10.     public PolicyThread(Socket socket){   
    11.         this.socket = socket;   
    12.     }   
    13.        
    14.     @Override  
    15.     public void run() {   
    16.         try {   
    17.             //接收并發送Flex安全驗證請求   
    18.             BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));   
    19.             PrintWriter pw = new PrintWriter(socket.getOutputStream());   
    20.             char[] by = new char[22];   
    21.             br.read(by, 022);   
    22.             String s = new String(by);   
    23.             if(s.equals(policy_xml)){   
    24.                 System.out.println("接收policy-file-request認證");   
    25.                 pw.print(cross_xml);   
    26.                 pw.flush();   
    27.                 br.close();   
    28.                 pw.close();   
    29.                 socket.close();   
    30.                 System.out.println("完成policy-file-request認證");   
    31.             }   
    32.         } catch (IOException e) {   
    33.             if(!socket.isClosed()){   
    34.                 try {   
    35.                     socket.close();   
    36.                 } catch (IOException e1) {   
    37.                     e1.printStackTrace();   
    38.                 }   
    39.             }   
    40.             throw new RuntimeException("執行policy認證時發生異常",e);   
    41.         }   
    42.     }   
    43.   
    44. }  
    Java代碼  
    1. public class PolicyServer implements Runnable{   
    2.        
    3.     private final int policy_port = 843;   
    4.     private boolean status = true;   
    5.        
    6.     private ServerSocket server = null;   
    7.     @Override  
    8.     public void run() {   
    9.         //創建安全驗證服務器   
    10.         server = SocketUtil.getServerSocket(policy_port);   
    11.            
    12.         while(status){   
    13.             Socket socket = SocketUtil.getSocket(server);   
    14.             new Thread(new PolicyThread(socket)).start();   
    15.         }   
    16.     }   
    17.        
    18.        
    19.     /**  
    20.      * 啟動服務器  
    21.      */  
    22.     public void startPolicy(){   
    23.         new Thread(this).start();   
    24.     }   
    25.        
    26.     /**  
    27.      * 關閉服務器  
    28.      */  
    29.     public void stopPolicy(){   
    30.         status = false;   
    31.         if(server!=null && !server.isClosed()){   
    32.             try {   
    33.                 server.close();   
    34.             } catch (IOException e) {   
    35.                 e.printStackTrace();   
    36.             }   
    37.         }   
    38.     }   
    39. }  
     
    Flex客戶端向Java發送第一次Socket請求(例子里的端口號是10086)時,ServerSocket843端口會收到安全沙箱驗證,隨后server將正確的驗證消息返回給Flex客戶端,Flex認證成功后真正的10086端口Socket連結就已經搭建了,隨后雙方就可以暢通無阻通信了(一次會話只進行一次沙箱驗證)。


    • Servlet啟動ServerSocket
    我通常比較喜歡創建一個servlet,在web.xml中配置容器啟動時運行servlet的init方法,這樣端口號為10086和843的serverSocket就會啟動:
    Java代碼  
    1. public class InitServers extends HttpServlet {   
    2.     private static final long serialVersionUID = 1L;   
    3.           
    4.     /**  
    5.      * @see HttpServlet#HttpServlet()  
    6.      */  
    7.     public InitServers() {   
    8.         super();   
    9.     }   
    10.   
    11.     /**  
    12.      * @see Servlet#init(ServletConfig)  
    13.      */  
    14.     public void init(ServletConfig config) throws ServletException {   
    15.         new PolicyServer().startPolicy();   
    16.         new SocketServer().startSocket();   
    17.     }   
    18.   
    19.     /**  
    20.      * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)  
    21.      */  
    22.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {   
    23.         // TODO Auto-generated method stub   
    24.     }   
    25.   
    26.     /**  
    27.      * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)  
    28.      */  
    29.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {   
    30.         // TODO Auto-generated method stub   
    31.     }   
    32.   
    33. }  
     web.xml

    Xml代碼  
    1. <servlet>  
    2.         <display-name>InitServers</display-name>  
    3.         <servlet-name>InitServers</servlet-name>  
    4.         <servlet-class>socket.InitServers</servlet-class>  
    5.         <load-on-startup>1</load-on-startup>  
    6.     </servlet>  
     
    以上一個完整的Flex+Java的Socket通信就完成了。
    主站蜘蛛池模板: 国产乱码免费卡1卡二卡3卡| 免费一级特黄特色大片在线| 亚洲六月丁香婷婷综合| 四虎成人免费网站在线| 精品一区二区三区高清免费观看| 亚洲国产精品自在线一区二区| 久久久久久久久免费看无码| 国产vA免费精品高清在线观看| 亚洲熟妇av一区| 亚洲精品国产精品乱码不卡| 亚洲黄色免费观看| 一级黄色免费毛片| 亚洲13又紧又嫩又水多| 国产亚洲精午夜久久久久久| 噼里啪啦电影在线观看免费高清| 两个人的视频www免费| 亚洲中文无码永久免费| 国产成A人亚洲精V品无码性色| 免费看大美女大黄大色| 日本中文一区二区三区亚洲| 一区二区三区观看免费中文视频在线播放 | 亚洲国产精品无码久久98 | 免费人成视网站在线观看不卡| 性xxxx视频免费播放直播| 黄色免费网址大全| 亚洲成年网站在线观看| 亚洲AV综合色区无码一区| 伊在人亚洲香蕉精品区麻豆| 久久不见久久见中文字幕免费 | 亚洲精品高清在线| 拨牐拨牐x8免费| 亚洲电影免费在线观看| 一级毛片**免费看试看20分钟 | 在线看片v免费观看视频777| 免费无码又爽又刺激网站| 国产成人高清亚洲一区久久| 国产成人精品日本亚洲18图| 久久亚洲精品中文字幕| 亚洲国产精品无码专区在线观看| 亚洲精品黄色视频在线观看免费资源 | 亚洲欧美日本韩国|