关于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("接收数据\n");

            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+"\n");

                if(obj.checkRuesult)

                {

                    infoTxt.appendText("登陆成功"+"\n");

                    sessions = obj.session;

                    RequestFun();

                }

                else

                {

                    infoTxt.appendText("登陆失败"+"\n");

                }

                break;

                

                case "roleInit":

                infoTxt.appendText("第二次接收到的数据为"+obj.session+","+obj.roleName+","+obj.sceneInfo+","+obj.roleLocation+"\n");

                infoTxt.appendText("当前的session为:"+obj.session+",将人物"+obj.roleName+"移动到地图"+obj.sceneInfo +"的"+obj.roleLocation+"的位置"+"\n"); 

                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("连接成功"+"\n");

            requestObj = new Object();

            requestObj = {event:"cookie",cookie:"cookieMsg"};

            socket.writeObject(requestObj);

            socket.flush();

        }

        

        //错误处理

        private function ioErrorHandler(event:IOErrorEvent):void {

            infoTxt.appendText("ioErrorHandler信息: " + event+"\n");

        }



        //安全问题处理

        private function securityErrorHandler(event:SecurityErrorEvent):void {

            infoTxt.appendText("securityErrorHandler信息: " + event+"\n");

        }

        

        //关闭Socket连接

        private function closeHandler(event:Event):void {

            infoTxt.appendText("连接关闭"+"\n");

        }

    }

} 

  

该文的评论如下:

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

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

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

你可能感兴趣的:(socket)