zoukankan      html  css  js  c++  java
  • Flex Socket与Java通信实例说明(转)

    Flex Socket与Java通信实例说明(转) 

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    这两天一直在flex的Socket ,现在终于懂了很多。由浅到深一步一步深入。慢慢体会实例,虽然实例都是在网上找的,但也经过了我的测试。我比较喜欢注释,也注释了很多。

    跟着走你就会懂。。

    Flex端 和 Java端, 先运行Java端启动服务。然后在测试Flex。

    实例一:

    Flex端:

    <?xml version="1.0" encoding="utf-8"?>

    <mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="349" height="326"

    creationComplete="initApp()" showCloseButton="true" >

    <mx:Script>

      <![CDATA[

       /**

         当运行在服务tocmat上面是,安全沙漏箱问题

         运行在本地文件上,正常

         Why ?

        这个问题,我在web上也测试了的,结果成功了。配置好策略文件

        */

      

       private var socket:Socket;

      

       internal function initApp():void{

        socket = new Socket(); //new出来 ,这时候才能被使用

        socket.connect("localhost",8080); //连接服务器 , 参数 host:String,prot:int

        socket.addEventListener(Event.CONNECT,funConnect); //监听是否连接上服务器

        socket.addEventListener(Event.CLOSE,funClose); //监听服务器是否关闭

       }

      

       private function funConnect(event:Event):void {

        myText.text+="已经成功连接到服务器! ";

       }

      

       private function funClose(event:Event):void {

        myText.text+="和服务器断开! "

       }

      ]]>

    </mx:Script>

    <mx:TextArea id="myText" x="10" y="10" width="285" height="250" />

    </mx:TitleWindow>

     
    Java 端:
    package f1.f1_005.socket;
     
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
     
    public class Server1 {
     
    public static void main(String[] args) {
      ServerSocket server = null;
      try {
       //使用指定的端口号创建了一服务器套接字对象。
       server = new ServerSocket(8888);
       System.out.println("服务器套接字已经被创建");
       while(true){
        System.out.println("等待客户机");
        //调用accept()方法来等待客户机的连接请求。 api:倾听一个连接被使这插座,接受它
        Socket socket = server.accept(); 
        System.out.println("已与客户机连接");
       }
      } catch (IOException e) {
       System.out.println(e);
       e.printStackTrace();
      } finally {
       try {
        if(server!=null)
         server.close(); //关闭服务器套接字。如果一直没有客户机器提出连接请求,服务器套接字将会继续等待。
       } catch (IOException e) {
        e.printStackTrace();
       } 
      }
    }
     
    }
     
    -------------------------------------------------------------------------------------------
    实例二:
    Flex端:
    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp();"
    >
    <mx:Script>
      <![CDATA[
      
       private var socket:Socket = new Socket(); //定义Socket
       internal function initApp():void{
        socket.connect("127.0.0.1",8888); //连接服务器
        socket.addEventListener(Event.CONNECT, funConnect);
        socket.addEventListener(Event.CLOSE, funClose);
       }
       internal function funConnect(e:Event):void{
        myText.text+="连接已建立 ";
       }
       internal function funClose(e:Event):void{
        myText.text+="连接已关闭 ";
       }
      
       internal function sendMessage(msg:String):void{ //发送数据对应按钮click事件
        var message:ByteArray = new ByteArray(); //新建一个ByteArray存放数据
        //写入数据,writeUTFBytes方法,以utf-8格式传数据避免中文乱码
        // 表示:回车符(ACSII:13 或0x0d),就是我们常说的硬回车。 表示:换行(ACSII:10 或0x0a),就是我们常说的软回车。
        message.writeUTFBytes(msg+" "); // 是输出的HTML代码换行,客户看到的效果没有换行
        socket.writeBytes(message); //写入Socket的缓冲区
        socket.flush(); //调用flush方法发送信息
        myText.text+=msg+" "; //在客户端屏幕上输出发送的内容
        myInput.text=""; //清空发言框
       }
      
      ]]>
    </mx:Script>
     
    <mx:TextArea x="10" y="10" width="703" height="263" id="myText"/>
    <mx:TextInput x="10" y="297" width="605" id="myInput"/>
        <mx:Button x="648" y="297" label="发送" id="myBtn" click="sendMessage(myInput.text)"/>
    </mx:Application>
     
    Java端:
    package f1.f1_005.socket;
     
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
     
    public class Server2 {
    private BufferedReader reader;  //负责输入
    private ServerSocket server; //服务器套接字
    private Socket socket;
     
    public Server2(){} //缺省构造函数
    void StartServer(){ //启动服务器
      try {
       server = new ServerSocket(8888); //创建服务器套接字
       System.out.println("服务器套接字建立完毕");
       while(true){
        System.out.println("等待客户机");
        socket = server.accept(); //若客户机提出连接请求,与socket连接
        System.out.println("完成与客户机的连接");
        //获取socket输入流,“utf-8”这个编码设置是为了更好显示中文
        reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
        getMessage();//读取来自客户机的数据,并输出至画面上
       }
      } catch (IOException e) {
       System.out.println(e);
       e.printStackTrace();
      }
     
    }
     
    void getMessage(){ //读取来自套接字的信息
      try {
       while(true){ //循环
        String msg = reader.readLine();
        if(msg == null){break;}
        System.out.println("客户机:"+msg);
       }
      } catch (IOException e) {
       e.printStackTrace();
      } finally {
       try {
        System.out.println("客户机中断连接");
        if(reader!=null) reader.close();
        if(socket!=null) socket.close();
        reader = null;
        socket = null;
       } catch (IOException e) {
        e.printStackTrace();
       }
      }
    }
     
    public static void main(String[] args) {
      Server2 s2 = new Server2();
      s2.StartServer();
    }
     
    }
    -------------------------------------------------------------------------------------------
    实例三:
    Flex 端:
    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="353" height="336"
    creationComplete="initApp();" >
    <mx:Script>
      <![CDATA[
       import mx.utils.ObjectUtil;
       /*  ByteArray
        Class public class ByteArray 
        继承 ByteArray -->  Object 
        Implements IDataInput, IDataOutput 
        Subclasses ByteArrayAsset 
     
        属性:
        bytesAvailable : uint  [] 可从字节数组的当前位置到数组末尾读取的数据的字节数。
        defaultObjectEncoding : uint [] 指示用于新 ByteArray 实例的 ByteArray 类的默认对象编码。
        length : uint ByteArray 对象的长度(以字节为单位)。
        position : uint 将文件指针的当前位置(以字节为单位)移动或返回到 ByteArray 对象中。
     
        方法:
        ByteArray() 创建一个表示填充的字节数组的 ByteArray 实例,以便使用此类中的方法和属性来优化数据存储和数据流。
        writeUTF(value:String):void  将 UTF-8 字符串写入字节流。
        writeUTFBytes(value:String):void  将 UTF-8 字符串写入字节流。
        writeByte(value:int):void  在字节流中写入一个字节。
        writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void  
         将指定字节数组 bytes(起始偏移量为 bytes,从 0 开始的索引)中包含 length 个字节的字节序列写入字节流。
         offset:uint (default = 0) — 从 0 开始的索引,表示在数组中开始写入的位置。
       
       
        
        Socket
        Class public class Socket 
        继承 Socket  EventDispatcher  Object 
        Implements IDataInput, IDataOutput 
        类使 代码可以建立套接字连接并读取和写入原始二进制数据。它与 XMLSocket 类似,但没有指定接收或传输的数据格式。
       
        属性:
        bytesAvailable : uint [] 输入缓冲区中可读取的数据的字节数。
        connected : Boolean  [] 指示此 Socket 对象目前是否已连接。
        objectEncoding : uint 在写入或读取对象时,控制所使用的 AMF 的版本。
       
        方法:
        Socket(host:String = null, port:int = 0) 创建一个 Socket 对象。
        close():void 关闭套接字。 Socket 
        connect(host:String, port:int):void 将套接字连接到指定的主机和端口。 Socket 
        dispatchEvent(event:Event):Boolean 将事件调度到事件流中。 EventDispatcher 
        flush():void 对套接字输出缓冲区中积累的所有数据进行刷新。 
        readByte():int 从套接字读取一个带符号字节。 Socket 
           readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void 从套接字读取 length 参数所指定的数据的字节数。 
        readMultiByte(length:uint, charSet:String):String 使用指定的字符集,从该字节流读取一个多字节字符串。
         readUnsignedByte():uint 从套接字读取一个无符号字节。 Socket 
           readUnsignedInt():uint 从套接字读取一个无符号的 32 位整数。 Socket 
           readUnsignedShort():uint   从套接字读取一个无符号的 16 位整数。 
        readUTF():String   从套接字读取一个 UTF-8 字符串。 Socket 
           readUTFBytes(length:uint):String 从套接字读取 length 参数所指定的 UTF-8 数据的字节数,并返回一个字符串。 
         writeByte(value:int):void  将一个字节写入套接字。 Socket 
           writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void 从指定的字节数组写入一系列字节。 
         writeMultiByte(value:String, charSet:String):void 使用指定的字符集,从该字节流写入一个多字节字符串。 Socket 
           writeObject(object:*):void 以 AMF 序列化格式将一个对象写入套接字。 Socket 
           writeShort(value:int):void 将一个 16 位整数写入套接字。 Socket 
           writeUnsignedInt(value:uint):void 将一个无符号的 32 位整数写入套接字。 Socket 
           writeUTF(value:String):void 将以下数据写入套接字:一个无符号 16 位整数,它指示了指定 UTF-8 字符串的长度(以字节为单位),后面跟随字符串本身。 Socket 
           writeUTFBytes(value:String):void 将一个 UTF-8 字符串写入套接字。 
     
        事件: Event.XX
        close 在服务器关闭套接字连接时调度。 Socket 
           connect 在建立网络连接后调度。 Socket 
           deactivate Flash Player 或 AIR 应用程序失去操作系统焦点并变为非活动状态时调度。 EventDispatcher 
           ioError 在出现输入/输出错误并导致发送或加载操作失败时调度。 Socket 
           securityError 若对 Socket.connect() 的调用尝试连接到调用方安全沙箱外部的服务器或端口号低于 1024 的端口,则进行调度。 Socket 
           socketData 在套接字接收到数据后调度。 
     
        */
       private var socket:Socket = new Socket();
       private var intClient:int; //定义客户端数字出拳
       private var intServer:int; //定义服务端数字出拳
       private var intSY:int; //定义输赢判断
       private var strClient:String; //客户端文字出拳
       private var strServer:String; //服务端的文字出拳
      
       internal function initApp():void{
        socket.connect("127.0.0.1",8888);
        socket.addEventListener(Event.CONNECT,funConnect);
                    socket.addEventListener(Event.CLOSE,funClose);
                    socket.addEventListener(ProgressEvent.SOCKET_DATA,funSocket);
       }
       internal function funConnect(e:Event):void{
        myText.text+="连接已建立 ";
       }
       internal function funClose(e:Event):void{
        myText.text+="连接已关闭 ";
       }
      
       private function sendMessage(msg:String):void{
        var message:ByteArray = new ByteArray();
        message.writeUTF(msg); //发送出拳数字
        socket.writeBytes(message);
        socket.flush();
        intClient=int(msg);
        switch(intClient){ //将数字转换成文字用于发布到屏幕上
         case 0:
                                strClient="剪刀";
                                break;
                        case 1:
                                strClient="锤";
                                break;
                        case 2:
                                strClient="包袱";
                                break;
        }
        myText.text+="你出:"+strClient+";  ";
                    myInput.text="";
       }
      
       internal function funSocket(e:ProgressEvent):void{ //接到服务器信息
        var msg:String="";
        while(socket.bytesAvailable)
        {
         msg=socket.readUTF();
         intServer=int(msg);
         intSY=intClient-intServer; //通过数值判断输赢
         switch(intServer) //将数字转换成文字用于发布到屏幕上
                        {
                            case 0:
                                    strServer="剪刀";
                                    break;
                            case 1:
                                    strServer="锤";
                                    break;
                            case 2:
                                    strServer="包袱";
                                    break;
                        }
                        myText.text+="服务器出:"+strServer+";  ";
                        //判断输赢的算法
                        if(intSY>0&&intSY<2)
                        {
                                myText.text+=" 结果:你赢了 ";
                        }else if(intClient==intServer)
                        {
                                myText.text+=" 结果:平手 ";
                        }else if(intSY<0&&intSY>-2)
                        {
                                myText.text+=" 结果:你输了 ";
                        }else if(intSY>=2)
                        {
                                myText.text+=" 结果:你输了 ";
                        }else if(intSY<=-2)
                        {
                                myText.text+=" 结果:你赢了 ";
                        }
                        // myText滚动到最下面
                        myText.verticalScrollPosition = myText.maxVerticalScrollPosition;
        }
       }
      
      
      ]]>
    </mx:Script>
     
    <mx:TextArea x="10" y="32" width="331" height="263" id="myText"/>
        <mx:TextInput x="10" y="303" width="245" id="myInput"/>
        <mx:Button x="273" y="304" label="发送" id="myBtn" click="sendMessage(myInput.text)"/>
        <mx:Label x="10" y="10" text="规则:0代表剪刀;1代表锤;2代表包袱" width="331" fontWeight="bold"/>
    </mx:Application>
     
    Java 端:
    package f1.f1_005.socket;
     
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Random;
    import java.util.Vector;
     
    /**
    知识点:套接字管理器(Vector)会将于客户机连接的套接字添加到其列表中,在客户机断开连接后,在将相应的套接自从列表中删除,从中可以看出,客户机连接数与列表中添加套接字数目是一致的。
    Vector sManager=new Vector();
    sManager.add(socket);  // 向列表添加套接字
    sManager.remove(socket);   //从列表移除套接字
    sManager.size();  //获取客户机连接数
    */
    public class Server3 {
     
    private ServerSocket server;
    //Vector 类提供了实现可增长数组的功能,随着更多元素加入其中,数组变的更大。
    Vector sManager = new Vector(); //管理套接字的Vector
    Random rnd = new Random(); //创建随机数的发生器
     
    public Server3(){}
    void startServer() //运行服务器
    {
      try {
       server = new ServerSocket(8888);
       System.out.println("服务器套接字已创建成功!");
       while (true)
       {
        Socket socket = server.accept();
        System.out.println("已经与客户机连接");
        new KBBCom_Thread(socket).start();
        sManager.add(socket);
        System.out.println("当前客户机连结数:"+sManager.size());
       }
      } catch (IOException e) {
       e.printStackTrace();
      }
    }
     
    public static void main(String[] args) {
      Server3 server=new Server3();
            server.startServer();
    }
     
    class KBBCom_Thread extends Thread  //与客户机进行通信的线程累
    {
      Socket socket; //套接字引用变量
      private DataInputStream reader; //套接字输入流
      private DataOutputStream writer;
     
      KBBCom_Thread(Socket socket){ //构造函数
       this.socket = socket;
      }
     
      public void run(){
       try {
        //获取套接字的输入输出流
        reader = new DataInputStream(socket.getInputStream());
        writer = new DataOutputStream(socket.getOutputStream());
        String msg;
        //如果收到客户端发来的数据
        while((msg=reader.readUTF())!= null){
         //向客户机传送0-2之间的整型随机数
         writer.writeUTF(rnd.nextInt(3)+" ");
         writer.flush();
         System.out.println("来自客户机:"+msg);
        }
       } catch (IOException e) {
        e.printStackTrace();
       } finally {
        try {
         sManager.remove(socket); //删除套接字
         //关闭输入输出流及套接字
         if(reader!=null)reader.close();
         if(writer!=null)writer.close();
         if(socket!=null)socket.close();
         reader=null;
         writer=null;
         socket=null;
         //向屏幕输出相关信息
         System.out.println("客户机离开");
                        System.out.println("当前客户机的连接数:"+sManager.size());
        } catch (IOException e) {
         e.printStackTrace();
        }
       }
      
      }
    }
     
    }
     
     
    -------------------------------------------------------------------------------------------
    实例四:
    Flex 端:
    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    creationComplete="initApp();" width="369" height="326">
    <mx:Script>
      <![CDATA[
       private var socket:Socket = new Socket();
      
       internal function initApp():void
       {
        socket.connect("192.168.0.56",8888);//执行连接 //localhost==127.0.0.1
                    //监听连接成功事件
                    socket.addEventListener(Event.CONNECT,funConnect);
                    //监听关闭事件
                    socket.addEventListener(Event.CLOSE,funClose);
                    //监听服务器新信息
                    socket.addEventListener(ProgressEvent.SOCKET_DATA,funSocket);
       }
       internal function funConnect(e:Event):void
       {
        myText.text+="连接已建立 ";
       }
       internal function funClose(e:Event):void
       {
        myText.text+="连接已关闭 ";
       }
      
       internal function sendMessage(msg:String):void
       {
        //新建一个ByteArray来存放数据
                 var message:ByteArray=new ByteArray();
                 //写入数据,使用writeUTFBytes以utf8格式传数据,避免中文乱码
                 message.writeUTFBytes(msg+" ");
                 //写入socket的缓冲区
                 socket.writeBytes(message);
                 //调用flush方法发送信息
                 socket.flush();
                 //清空消息框
                    myInput.text="";
       }
      
       internal function funSocket(e:Event):void
       {
        var msg:String="";
                 //循环读取数据,socket的bytesAvailable对象存放了服务器传来的所有数据
                 while(socket.bytesAvailable)
                 {
                  //强制使用utf8格式,避免中文乱码
                  msg += socket.readMultiByte(socket.bytesAvailable,"utf8"); //UTF-8
                  //使用 换行符号把信息切开
                  var arr:Array = msg.split(" ");
                  for(var i:int=0;i<arr.length;i++)
                  {
                   if(arr[i].length > 0){
                    //正则表达式,回车符
                    var myPattern:RegExp=/ /;
                    //删除回车符
                    arr[i] = arr[i].replace(myPattern,"");
                    //在聊天框中输出
                    myText.text+=arr[i]+" ";
                   }
                  }
                  myText.horizontalScrollPosition = myText.maxVerticalScrollPosition; //滚动到最下面
                 }
       
       }
      
      ]]>
    </mx:Script>
    <mx:TextInput x="10" y="10" width="344" text="名字" id="myName"/>
    <mx:TextArea x="10" y="42" width="344" height="247" id="myText"/>
        <mx:TextInput x="10" y="297" width="270" id="myInput"/>
        <mx:Button x="288" y="298" label="发送" id="myBtn" click="sendMessage(myName.text+':'+myInput.text)"/>
    </mx:Application>
     
    Java 端:
    package f1.f1_005.socket;
     
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Vector;
     
    public class Server4 {
     
    private ServerSocket server;
    private BManager bMan=new BManager();  //消息广播
     
    public Server4() {}
    void startServer()  //启动服务器
    {
      try {
       server=new ServerSocket(8888); //创建服务器套接字
       System.out.println("服务器套接字建立完毕");
       while(true)
                {
        Socket socket=server.accept();//若客户机提请求,socket连接
        new Chat_Thread(socket).start();//启动线程
        bMan.add(socket); //添加套接字
        bMan.sendClientInfo(); //使用套接字输出当前聊天人数
                }
      } catch (IOException e) {
       System.out.println(e);
       e.printStackTrace();
      }
     
    }
     
    class Chat_Thread extends Thread{ //与客户机进行通信的线程累
      Socket socket; //套接字引用变量
      private BufferedReader reader; //引用套接字输入流;
      private PrintWriter writer;  //引用套接字输出流;
     
      Chat_Thread(Socket socket){ //构造函数
       this.socket = socket;
      }
     
      public void run() {
       try {
        reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf8"));//utf8UTF-8
        //PrintWriter 的第二个参数:autoFlush - A boolean; if true, the println, printf, or format methods will flush the output buffer
        writer = new PrintWriter(socket.getOutputStream(),true);
        String msg;
        //从输出流获取信息
        while((msg=reader.readLine()) != null){
         System.out.println(msg);
                        //向所有客户机传送信息
         bMan.sendToAll(msg);
        }
       } catch (IOException e) {
        e.printStackTrace();
       } finally {
        try { //从消息广播者立标中删除socket
         bMan.remove(socket);
         if(reader!=null) reader.close();
         if(writer!=null) writer.close();
         if(socket!=null) socket.close();
         reader=null;
         writer=null;
         socket=null;
         System.out.println("客户机离开");
         //向所有客户机传送当前连接数
                        bMan.sendClientInfo();
        } catch (IOException e) {
         e.printStackTrace();
        }
       }
      }
     
     
    }
     
    public static void main(String[] args) {
      Server4 server=new Server4();
            server.startServer();
    }
     
    }
     
    //消息广播者类,继承Vector类
    class BManager extends Vector{ //消息广播者类,继承Vector类
    BManager (){}//构造函数
     
    void add(Socket socket) {
      super.add(socket);  //添加套接字
    }
     
    void remove(Socket socket) {
      super.remove(socket); //删除套接字
    }
     
    //向所有客户机传送消息,同步化方法。
    synchronized void sendToAll(String msg) {
      PrintWriter writer = null; //输出流
      Socket socket;
      for (int i = 0; i < size(); i++) {
       socket = (Socket)elementAt(i);
       try {
        //获取第i个套接字输出流
        writer = new PrintWriter(socket.getOutputStream(),true);  //就是因为掉了个ture ,客服端就显示不了数据
       } catch (IOException e) {
        e.printStackTrace();
       }
       //使用第i各套接字输出流,输出消息
       if(writer!=null)  writer.println(msg);
      }
    }
     
    //向所有客户机发送当前聊天人数
    synchronized void sendClientInfo(){
      String info = "当前聊天人数:"+size();
      System.out.println(info);
            sendToAll(info);
    }
    }
     
    -------------------------------------------------------------------------------------------
    实例五:
    Flex 端:
    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" fontSize="12" 
    creationComplete="initApp()" width="547" height="326" >
    <mx:Script>
    <![CDATA[
      import mx.controls.Alert;
      import com.flex.f018.MyLogin;
      import flash.net.Socket;
      import flash.utils.ByteArray;
      import mx.managers.PopUpManager;
      import flash.events.MouseEvent;
     
      private var strPD:String="22--";//协议头判断
      private var socket:Socket=new Socket();
      private var win:MyLogin=new MyLogin();
      internal function initApp():void
      {
       win.width=240;
       win.height=94;
       win.x=153;
       win.y=116;
       PopUpManager.addPopUp(win,this,true);
       win.myBtn.addEventListener(MouseEvent.CLICK,funBtn);
       //socket.connect("127.0.0.1",8888);
       //socket.addEventListener(ProgressEvent.SOCKET_DATA,funSocket);
      }
      internal function funChoose(event:MouseEvent):void
      {
       var item:Object=myList.selectedItem;
       strPD="33--"+item+"--";
      }
      internal function funBtn(event:MouseEvent):void
      {
       myName.text=win.txtName.text;
       PopUpManager.removePopUp(win);
       socket.connect("127.0.0.1",8888);
       socket.addEventListener(Event.CONNECT,funConnect);
       //监听关闭事件
       socket.addEventListener(Event.CLOSE,funClose);
       socket.addEventListener(ProgressEvent.SOCKET_DATA,funSocket);
       myList.addEventListener(MouseEvent.CLICK,funChoose);
       sendMessage("11"+myName.text);
     
      }
     
      internal function funConnect(event:Event):void
      {
       trace("[log] funConnect:连接已建立");
       myText.text+="连接已建立 ";
       //sendMessage("11"+myName.text);
      }
      internal function funClose(e:Event):void
      {
       trace("[log] funClose:连接已关闭");
       myText.text+="连接已关闭 ";
      }
      internal function sendMessage(msg:String):void
      {
       trace("[log] sendMessage :" + msg);
       var message:ByteArray=new ByteArray();
       message.writeUTFBytes(msg+" ");
       socket.writeBytes(message);
       socket.flush();
       myInput.text="";
      }
      internal function funSocket(event:ProgressEvent):void
      {
       trace("[log] funSocket ");
       var msg:String="";
       var pd:String=""; //协议判断字符
       var intCD:int=0;
       while(socket.bytesAvailable)
       {
       
        msg=socket.readMultiByte(socket.bytesAvailable,"utf8");
        trace("[log] funSocket msg:"+msg);
        pd=msg.substring(0,2);
        intCD=msg.length;//获取字符串长度  
        if(pd=="11") // 11--UserName
        { // 11开头表示更新用户列表
        
         msg=msg.substring(4,intCD);
         var myPattern2:RegExp=/ /;//清除回车和换行符
         //var myPattern3:RegExp=/ /;
         msg=msg.replace(myPattern2,'');
         //msg=msg.replace(myPattern3,'');
         var arrList:Array=msg.split("--");
         arrList.unshift("所有人");
         trace("[log] 11 arrList : " +arrList);
         myList.dataProvider=arrList;
        
        }else if(pd=="22") // 22UserNamed登录了
        {
         msg=msg.substring(2,intCD);
         var arr:Array=msg.split(' ');
         for(var i:int=0;i<arr.length;i++)
         {
          if(arr[i].length>1)
          {
           var myPattern:RegExp=/ /;
           arr[i]=arr[i].replace(myPattern,'');
           myText.text+=arr[i]+" ";
          }
         }
         myText.verticalScrollPosition = myText.maxVerticalScrollPosition;//滚动到最下面
        }else if(pd=="33")
        {
        }
        else if(pd=="44") // 44当前在线认识:Size人
        {
         msg=msg.substring(2,intCD);
         labCount.text=msg;
        }
        else
        {}
       }
       
      }
    ]]>
    </mx:Script>
    <mx:TextArea x="10" y="10" width="344" height="279" id="myText"/>
    <mx:TextInput x="103" y="297" width="357" id="myInput"/>
    <mx:Button x="468" y="298" label="发送" id="myBtn" click="sendMessage(strPD+myName.text+'--'+myInput.text)"/>
    <mx:Label x="10" y="299" width="85" textAlign="right" id="myName" fontWeight="bold" color="#ffffff"/>
    <mx:List x="367" y="42" height="247" id="myList" width="170"></mx:List>
    <mx:Label x="367" y="13" width="170" id="labCount"/>
     
    </mx:Application>
     
    Java 端:
    package f1.f1_005.socket;
     
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.*;
     
    /*
    * 自定义的协议 
    * 收到消息: 11开头表示新加入了聊天用户;22开头表示公聊;33开头表示私聊
    * 发送消息:11开头表示更新用户列表;22开头表示发送到屏幕上;44发送在线人数
    */
    public class Server5 {
     
    private ServerSocket server;
    private BManager5 bMan = new BManager5();  //消息广播者
    //Map接口的HashMap类,元素拥有固定key值,key值不重复,这里用来存放在线用户
    Map<Socket, String> clientList = new HashMap<Socket, String>();
    public Server5(){} //构造函数
    public void startServer(){  //启动服务器
      try {
       server = new ServerSocket(8888); //创建服务器套接字
       System.out.println("服务器套接字建立完毕");
       while(true)
       {
        Socket socket = server.accept(); //若客户机提出请求,使用socket进行连接
        //String strIP = socket.getInetAddress().toString();//登陆者的ip
        new Chat_Thread(socket).start(); //启动线程
        bMan.add(socket); //添加套接字
        bMan.sendClientInfo(); //使用套接字输出当前聊天人数
        //funList(clientList);
        //bMan.sendToAll(strIP+"/加入聊天室");
       }
      } catch (IOException e) {
       System.out.println(e);
       e.printStackTrace();
      }
     
    }
     
    class Chat_Thread extends Thread{  //与客户机进行通讯的线程类
      private Socket socket; //x1
      private BufferedReader reader; //套接字输入流;
      private PrintWriter writer; //套接字输出流
     
      Chat_Thread(Socket socket){
       this.socket = socket; //this.socket就是x1处的socket
      }
     
      public void run(){
       try {
        reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf8"));
        //PrintWriter 的第二个参数:autoFlush - A boolean; if true, the println, printf, or format methods will flush the output buffer
        writer=new PrintWriter(socket.getOutputStream(),true);
        String msg; //msg获取消息
        // while 这样写,在关闭浏览器的时候,会进入finally  
        while((msg=reader.readLine())!=null) //while(true){
        {
    //     if((msg=reader.readLine())!=null){
          System.out.println(msg); //服务器屏幕输出消息
          String str = msg.substring(0,2); //截取前两个个字符
          int a=Integer.parseInt(str); //强制转换成int
          String[] arrMsg=msg.split("--"); //将获取的消息以"--"符号为标志分解成数组
          switch(a){
           case 11: //当消息以11开头的时候,将登陆者的信息储存到hashmap之中,并向客户端发送新的在线列表
            String strName = msg.substring(2);  //获取登陆者名字,消息格式“11eko”
            System.out.println(strName+"登陆了"); //服务器屏幕输出谁登陆了
            bMan.sendToAll("22"+strName+"登陆了"); //广播谁登陆了
            clientList.put(this.socket,strName); //加入到HashMap中
            funList(clientList); //广播在线列表
            break;
           case 22: //当消息以22开头的时候,表示公聊,内容为“22--eko--内容”
            System.out.println("公聊");
            //构造消息,arrMsg[0]=消息头,arrMsg[1]消息发送者,arrMsg[2]消息内容
            msg=arrMsg[0]+arrMsg[1]+"说:"+arrMsg[2];
            bMan.sendToAll(msg);
            break;
           case 33: //消息以33开头时候,内容为“33--sandal--eko--内容”
            //arrMsg[1]为说话对象,arrMsg[2]为说话人,arrMsg[3]为消息内容
            if(arrMsg[1].equals("所有人"))//当说话对象为"所有人"的时候
            {
             //构造消息"22eko说:内容"
             msg="22"+arrMsg[2]+"说:"+arrMsg[3];
             //向所有人发送消息
             bMan.sendToAll(msg);
            }else //其他情况就是向具体的某个人发送消息了
            {
             Socket socketOne=new Socket();
             System.out.println("私聊");
             Set set = clientList.keySet(); //使用keySet方法获取所有key值
             Iterator it = set.iterator(); //使用Iterator(迭代器)来遍历数据
             while (it.hasNext()) { //返回是否还有没被访问过的对象
              Object ok=it.next(); //返回下一个没被访问过的对象
              Object ov=clientList.get(ok); //get方法返回拥有key的元素
              if(ov.equals(arrMsg[1])) //如果在client中找到"消息发给谁"的时候,发给对方??????
              {
               socketOne=(Socket)ok; //强制转换成key值类型;
               bMan.sendToONE(socketOne,"22(悄悄话)"+arrMsg[2]+"对你说:"+arrMsg[3]);
              }else if(ov.equals(arrMsg[2])) //如果在client中找到"发消息的人"的时候,发给他自己???????
              {
               socketOne=(Socket)ok;
               bMan.sendToONE(socketOne,"22(悄悄话)你对"+arrMsg[1]+"说:"+arrMsg[3]);
              }
             }
            }
            break;
          }
    //     }
        }
       } catch (IOException e) {
        e.printStackTrace();
       } finally {
        try {
         if(clientList.containsKey(socket))
         {
          bMan.sendToAll("22"+clientList.get(socket)+"离开了...");//广播消息,谁离开了
          clientList.remove(socket); //删除socket
          funList(clientList); //广播在线列表
         }
         bMan.remove(socket);
         if(reader !=null) reader.close();
         if(writer !=null) writer.close();
         if(socket !=null) socket.close();
         reader=null;
         writer=null;
         socket=null;
         System.out.println("客户机离开");
         bMan.sendClientInfo();//广播在线人数
        } catch (Exception e) {}
       }
      }
     
      void funList(Map clientList) // 广播在线列表???????б?
      {
       String strList = ""; //在线列表
       Set set = clientList.keySet(); //使用keySet方法获取所有key值
       System.out.println(set);
       Iterator it = set.iterator(); //使用Iterator(迭代器)来遍历数据
       System.out.println(it);
       while (it.hasNext()) { //把用户名称发给在线所有客户端 
        strList+="--";
        strList+=clientList.get(it.next());
       }
       bMan.sendToAll("11"+strList);
      }
    }
     
    public static void main(String[] args){
      Server5 server = new Server5();
      server.startServer();
    }
    }
     
    class BManager5 extends Vector
    {
    BManager5(){}
    void add(Socket socket){ 
      super.add(socket);
    }
     
    void remove(Socket socket)
    {
      super.remove(socket);
    }
     
    synchronized void sendToAll(String msg){ //给所有人广播函数
      PrintWriter writer = null ;
      Socket socket;
      for (int i = 0; i < size(); i++) { //执行循环
       socket = (Socket)elementAt(i); //获取第i个套接字
       try {
        //获取第i个套接字输出流
        writer = new PrintWriter(socket.getOutputStream(),true);
       } catch (IOException e) { }
       System.out.println(msg);
       //使用第i各套接字输出流,输出消息
       if(writer!=null)
        writer.println(msg);
      }
    }
     
    synchronized void sendToONE(Socket socket,String msg){ //私聊函数
      PrintWriter writer=null;
      Socket sock;
      for(int i=0;i<size();i++)
      {
       sock = (Socket)elementAt(i);
       if(sock == socket){ //与给所有人广播函数类似,仅加入了判断,只有当socket管理器中的socket等于传入的socket的时候才发送消息
        try
        {
         writer=new PrintWriter(sock.getOutputStream(),true);
        }catch(Exception ie){}
        if(writer!=null)writer.println(msg);
       }
      }
    }
     
    synchronized void sendClientInfo(){
      int a = size();
      String msg ="44当前在线人数:" +a+"人";
      sendToAll(msg);
    }
     
    }
  • 相关阅读:
    类与对象
    类的声明与实例化
    面向对象的基本概念
    css下拉导航栏代码
    面向对象的三大特性
    面向对象三大基本特性,五大基本原则
    dom事件
    PHP 流程
    权限 查找
    留言板案例
  • 原文地址:https://www.cnblogs.com/wzhanke/p/4817664.html
Copyright © 2011-2022 走看看