大家好,我是奶綠茶
今天來介紹一下 Adobe AIR ServerSocket
需求:
很多台電腦,在同一個區網,要能彼此溝通,同時 Android 平版也要能傳接值。
解:
本來想如果就只有單 flash 的話, 可以使用 P2P 區網連線就決解了,
但因為 Andriod 平版也要能支援, 所以就改成 Socket 來溝通。

那為什麼不用 Java 架 Socket Server 就好了,因為我是閃客(因為用 Java 做動畫會死人)
AIR 端,使用ServerSocket 類別。
在畫面上就只放所有連線的 Client 列表,一個發送訊息的文字和Button, 一個接收的文字

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                       xmlns:s="library://ns.adobe.com/flex/spark"
                       xmlns:mx="library://ns.adobe.com/flex/mx"
        creationComplete="createComplete(event);"
        close="appCloseHandler()">
 
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 
 <fx:Script>
  <![CDATA[
  import flash.display.NativeWindow;
  import flash.events.Event;
  import flash.events.ProgressEvent;
  import flash.events.ServerSocketConnectEvent;
  import flash.net.ServerSocket;
  import flash.net.Socket;
  import flash.utils.ByteArray;
  import mx.collections.ArrayCollection;
  import mx.controls.Alert;
  import mx.events.FlexEvent;
 
 
  private var server :ServerSocket = new ServerSocket();
 
  [Bindable]
  private var serverActivity:Boolean = false;
 
  [Bindable]
  private var clientSockets:ArrayCollection = new ArrayCollection();
 
  //private var ipAddress  :String = "192.168.253.176";
  private var ipAddress  :String = "127.0.0.1";
  private var ipAddressPort :int = 9527;
 
  private function createComplete(e:FlexEvent):void {   
 
   try {
    server.bind(ipAddressPort, ipAddress);
    log( "bind:" + ipAddress+":"+ipAddressPort );
    server.addEventListener(ServerSocketConnectEvent.CONNECT , clientConnectedHandler);   
    server.listen();
    serverActivity = true;
   }catch (err:Error){
    log( err + "" );
    serverActivity = false;
    Alert.show(err.message);    
   }   
  }
 
  private function clientConnectedHandler(e:ServerSocketConnectEvent):void {
   //每當有新的 Client 連該進來, 就會觸發該函式。
   var clientSocket:Socket = e.socket;
   log( clientSocket.localAddress + ":" + clientSocket.localPort );
   clientSockets.addItem( clientSocket );
   clientSocket.addEventListener(Event.CLOSE , clientDisconnectedHandler);
   //偵聽當 Client 離線時。
   clientSocket.addEventListener(ProgressEvent.SOCKET_DATA, onClientSocketData );
   //偵聽 Client 發出的訊息
  }
 
  private function onClientSocketData(e:ProgressEvent):void {
   // 讀取 Client 發出的訊息
   var buffer:ByteArray = new ByteArray();
   var clientSocket:Socket = e.currentTarget as Socket;
            clientSocket.readBytes( buffer, 0, clientSocket.bytesAvailable );
            log( "Received: " + buffer.toString() );   
  }
 
  private function clientDisconnectedHandler(e:Event):void {
   // 當 Client 離線時。
   e.currentTarget.removeEventListener( e.type , arguments.callee );
   clientSockets.removeItemAt( clientSockets.getItemIndex(e.target));
  }
  private function log(o:Object):void {
   textArea.text += o +"\n";
  }
 
  private function writeDataToSockets(e:Event):void {
   var msg:String = textInput.text;
   if (msg == "") {
    return;
   }   
   trace( "ServerSocketMain.writeDataToSockets ");
   // 對所有的 Client 發出訊息。
   for each (var socket:Socket in clientSockets) {
    if (socket.connected) {     
     try {
      socket.writeUTF(msg);
      socket.flush();
     }catch (err:Error){
      log(err);
     }     
    }
   }
  }
  private function appCloseHandler():void {  
   server.close();
   server = null;   
  } 
 
 
  ]]>
 </fx:Script>
 <s:HGroup width="100%" height="100%" paddingLeft="5">
  <s:List width="200" height="100%" dataProvider="{clientSockets}" labelField="localAddress"></s:List>
 
  <s:VGroup width="100%" height="100%">
   <s:HGroup width="600">
    <s:TextInput id="textInput" width="200" text="server send info to all client" />
    <s:Button x="130" y="10" label="Send" 
     click="writeDataToSockets(event)" 
     enabled="{textInput.text.length>0}" visible="{clientSockets.length>0}" />
   </s:HGroup> 
   <s:Button label="clear" click="{textArea.text=''}" enabled="{serverActivity}"/>
   <s:TextArea id="textArea" width="200" height="100%" editable="false" />
  </s:VGroup>
 </s:HGroup> 
</s:WindowedApplication>

在用 flash 寫一個 Client 端測試:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/halo"
      creationComplete="createSocket(event)">
 <s:layout>
  <s:VerticalLayout />
 </s:layout>
 <fx:Script>
  <![CDATA[
   import flash.events.Event;
   import flash.events.ProgressEvent;
   import flash.net.Socket;
   import mx.events.FlexEvent;
 
   protected var socket:Socket;
 
   private var ipAddress  :String = "127.0.0.1";
   private var ipAddressPort :int = 9527;
 
   protected function createSocket(event:FlexEvent):void {    
    socket = new Socket();
    socket.addEventListener(Event.CONNECT,socketConnected);
    socket.addEventListener(ProgressEvent.SOCKET_DATA, socketData);      
    socket.connect( ipAddress, ipAddressPort );    
   }   
   protected function socketConnected(e:Event):void{
    log("client - socket connected");
   }   
   protected function socketData(e:ProgressEvent):void{
    trace("client - socket data");
    //trace(socket.readUTF());    
    log(socket.readUTF());    
   }   
   private function callServerClickHandler():void {
    try {
     socket.writeUTF("callServer");
     socket.flush();
    }catch (err:Error){
     log(err);
    }
 
   }
   private function log(o:Object):void {
    textArea.text += o + "\n";
   }
 
  ]]>
 </fx:Script>
 <s:Button label="call Server" click="callServerClickHandler()" />
 <s:TextArea id="textArea"></s:TextArea>
</s:Application>

Java/Android 端
使用 Socket 類別
因為程式碼落落長,
有需要的朋友就直接下載 Android 端的程式碼,在這就不貼出來了

AIR
Java/Android