转自: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客户端接收到所有 的数据之后,再从该容器中将该对象读取出来,这样问题就解决了。 我们现在用的就是这个方法,经过无数的测试后,这个方法是可行的,直到现在我们的 服务器现在还运行的好好的。 这算是对这个问题的一个结贴吧,希望对大家有所帮助。