zoukankan      html  css  js  c++  java
  • 关于socket使用Amf直接进行对象传输的

    转自:topic.csdn.net/u/20080924/11/1b3ddc7c-4080-4b6c-b491-5cbf1fa7f631.html

    原文如下:

    问题如下: 服务器是用java写的,客户端是用actionscript(使用amf3)写的,但是服务器端只发送了两次信息, 客户端却接收到三次数据,服务器端也是同样的问题,接收到客户端的三次数据,但是客户端也只发了 两次信息。

    java服务器端的代码如下:

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.HashMap;
    
    import flex.messaging.io.SerializationContext;
    import flex.messaging.io.amf.ASObject;
    import flex.messaging.io.amf.Amf3Input;
    import flex.messaging.io.amf.Amf3Output;
    
    public class LgServerThread extends Thread
    {
        SerializationContext seri=new SerializationContext();//序列化输入输出流
        
        Amf3Output amfout=new Amf3Output(seri);//格式化输出流
        Amf3Input amfin=new Amf3Input(seri);//格式化输入流
        
        ByteArrayOutputStream baos=new ByteArrayOutputStream();//创建二进制输入流
        ByteArrayInputStream bais=null;//创建二进制输入流
        
        DataOutputStream dos=new DataOutputStream(baos);//转化二进制流为数据输出流
        DataInputStream dis=null;//创建输入流
        Socket socket;
        
        InputStreamReader isr;//将输入流信息由字符型转换为字节型
        BufferedReader br;//将输入流信息放入缓存
        
        OutputStreamWriter osw = null;//使用amf3格式将写入流中的数据编码成字节
        BufferedWriter bw;//用来封装OutputStreamWriter,以提高效率
        
        Boolean eventFlag=true;
        
        //LgServerThread的构造函数
        public LgServerThread(Socket socket)
        {
            this.socket=socket;
        }
        
        public void Init()
        {
            try {
                amfin.setInputStream(socket.getInputStream());
                amfout.setOutputStream(dos);
                
                isr=new InputStreamReader(socket.getInputStream());
                br=new BufferedReader(isr);//将流中的数据放入缓存
                
                osw=new OutputStreamWriter(socket.getOutputStream());//将字符流转化为字节流
                 bw=new BufferedWriter(osw);//封装osw对象,提高写入的效率
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
         
        public void run()
        {
             HashMap map;
            try {
                Init();
                while(eventFlag)
                {
                    ASObject message = ReceiveMsg();
                    
                    if(message!=null)
                    {
                        String event=(String)message.get("event");            
    
                        if(event!=null)
                        {
                            if(event.equals("cookie"))
                            {
                               map=new HashMap();
                               map.put("event", "checkMsg");
                               map.put("checkRuesult", "true");
                               map.put("session","thisissession");
                               
                               amfout.writeObject(map);//实际上是将map对象写入到dataoutstream流中
                               dos.flush();//清空缓存
                               
                               map=null;
                               
                                  byte[] messageBytes1=baos.toByteArray();//amf3数据
                                  socket.getOutputStream().write(messageBytes1);//向流中写入二进制数据    
                                  socket.getOutputStream().flush();
                            }
                            else if(event.equals("requestRoleInit"))
                            {
                                if(message.get("requestMsg").equals("roleInit"))
                                {
                                    map=new HashMap();
                                    map.put("event", "roleInit");
                                    map.put("session", "thisissession");
                                    map.put("roleName","estone");
                                    map.put("sceneInfo", "map.gif");
                                    map.put("roleLocation", "100/100");
                                        
                                    amfout.writeObject(map);//实际上是将map对象写入到 dataoutstream流中
                                    dos.flush();//清空缓存
                                    
                                    map=null;
                                    
                                    byte[] messageBytes2=baos.toByteArray();//amf3数据
                                    socket.getOutputStream().write(messageBytes2);//向流中写入二进制数据    
                                    socket.getOutputStream().flush();
                                }
                            }
                          }
                    }
                  }
            } 
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        public ASObject ReceiveMsg()
        {
            ASObject object=null;
            while(true)
            {
                    try {
                        object =(ASObject) amfin.readObject();
                        System.out.println();
                        System.out.println("<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>");
                        System.out.println(object);
                        System.out.println("<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>");
                        System.out.println();
                        
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                   }
                return object;
            }
        }
        
        public void SendMsg(byte[] message)
        {
            
       
    

      客户端代码ActionScript

    package cls
    {
        import flash.net.Socket;
        import flash.display.Sprite;
        import flash.events.*;
        import flash.text.TextField;
        
        public class SocketLink extends Sprite
        {
            private var socket:Socket;
            private var obj:Object;
            private var sessions:String;
            private var infoTxt:TextField;
            private var requestObj:Object;
            
            public function SocketLink(url:String,port:int):void
            {
                socket = new Socket();
                socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
                socket.addEventListener(Event.CONNECT, connectHandler);
                socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
                socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
                socket.addEventListener(Event.CLOSE, closeHandler);
                socket.connect(url,port);
            }
            
            public function init():void
            {
                var temp = this.parent;
                infoTxt = temp.infoTxt;
            }
            
            //接收服务器数据
            private function socketDataHandler(event:ProgressEvent):void {
                infoTxt.appendText("接收数据
    ");
                obj = new Object();
                obj=socket.readObject();
                for(var k in obj)
                {
                    trace(k+":"+obj[k]);
                }
                trace("----------------------------------");
                recievedData();
            }
            
            //测试接收到的数据
            private function recievedData()
            {
                switch(obj.event)
                {
                    case "checkMsg":
                    infoTxt.appendText("第一次接收到的数据为"+obj.checkRuesult+","+obj.session+"
    ");
                    if(obj.checkRuesult)
                    {
                        infoTxt.appendText("登陆成功"+"
    ");
                        sessions = obj.session;
                        RequestFun();
                    }
                    else
                    {
                        infoTxt.appendText("登陆失败"+"
    ");
                    }
                    break;
                    
                    case "roleInit":
                    infoTxt.appendText("第二次接收到的数据为"+obj.session+","+obj.roleName+","+obj.sceneInfo+","+obj.roleLocation+"
    ");
                    infoTxt.appendText("当前的session为:"+obj.session+",将人物"+obj.roleName+"移动到地图"+obj.sceneInfo +"的"+obj.roleLocation+"的位置"+"
    "); 
                    break;
                }
            }
            
            private function RequestFun():void
            {
                requestObj = new Object();
                requestObj = {event:"requestRoleInit",session:sessions,userName:"zhangfan",requestMsg:"roleInit"};
                socket.writeObject(requestObj);
                socket.flush();
            }
    
            //Socket已连接,发送数据
            private function connectHandler(event:Event):void {
                infoTxt.appendText("连接成功"+"
    ");
                requestObj = new Object();
                requestObj = {event:"cookie",cookie:"cookieMsg"};
                socket.writeObject(requestObj);
                socket.flush();
            }
            
            //错误处理
            private function ioErrorHandler(event:IOErrorEvent):void {
                infoTxt.appendText("ioErrorHandler信息: " + event+"
    ");
            }
    
            //安全问题处理
            private function securityErrorHandler(event:SecurityErrorEvent):void {
                infoTxt.appendText("securityErrorHandler信息: " + event+"
    ");
            }
            
            //关闭Socket连接
            private function closeHandler(event:Event):void {
                infoTxt.appendText("连接关闭"+"
    ");
            }
        }
    } 
    

      

    该文的评论如下:

    A:我也遇到了相似的问题,客户端的一条数据被分成了两条发送给服务端

    B:好像听别人说起过,sorket通信时,如果传送字符串较长的话,会自动分开后传过去。

    楼主:关于这个问题现在我们已经解决了,但是由于一些原因,现在还不能将该问题的源码 放在论坛上面,但是我在这里讲解一下这个问题的一些思路: 由于socket传输数据时是按固定的大小传送字节数据的,但是在flash客户端读取的 时候是靠一个readObject方法,也就是每次flash客户端读取的时候都是按一个完整 的对象来读取每一次的socket的,但是在服务器端有可能socket将一个完整的序列化 对象给分开来传输,这也就是我们遇到的问题,为什么有时候能够正常接收到数据,而 有时候却只是接收到数据却无法读取的原因。解决的办法就是在客户端读取数据之前, 先将数据存放在一个容器里面(这个需要大家自己去想了),等flash客户端接收到所有 的数据之后,再从该容器中将该对象读取出来,这样问题就解决了。 我们现在用的就是这个方法,经过无数的测试后,这个方法是可行的,直到现在我们的 服务器现在还运行的好好的。 这算是对这个问题的一个结贴吧,希望对大家有所帮助。  

  • 相关阅读:
    linux kill命令以及 信号
    rhel7 系统服务——unit(单元)
    redis集群在线迁移
    二、主目录 Makefile 分析(3)
    二、主目录 Makefile 分析(2)
    二、主目录 Makefile 分析(1)
    一、文档目录分析
    Linux下解压缩
    设备树
    轮询
  • 原文地址:https://www.cnblogs.com/regalys168/p/3614687.html
Copyright © 2011-2022 走看看