最近研究了下as3 Socket 跟Java服务器的通信,一些心得分享下。
客户端的代码如下:
Java服务器端的代码如下:
刚开始的时候as3读取包的时候直接readInt()等读的,遇到了一些莫名其妙的问题,不是遇到文件尾,就是读出了一系列乱七八糟的数据,但是调用setTimeout过段时间再读的话,不管这个时间有多小,例如上面的0....1,都会读取正确。后来断点看了一下,每次读的时候_socket的bytesAvailable即服务器发的包长度在不断的变化,很多情况下都是比服务器发的长度小,这样用字节流读取的话肯定就会遇到文件尾的错误了。因此在as3 Socket通信中读取服务器数据的时候一定要验证服务器包的完整性,即在代码中:
当客户端收到的包的长度 >= 服务器所发的包的长度时, 再读取一次, 而不是一收到数据就立即读取。 但是相反的是, Java代码可以直接读取的, 为什么是这样暂时没有搞清楚, 看来还是要仔细学习一下TCP / IP通信。 究其原因, 应该是AS3每收到一次服务器发的数据, 即一串二进制流吧, 就会派发ProgressEvent.SOCKET_DATA事件, 但同一时间收到的并不是一个完整的通信包, 而只是一部分, 大概就相当于加载进度条了, 每加载一部分就会派发事件, 而不是加载完成才派发, 加载完成派发Event.COMPLETED事件
客户端的代码如下:
package com { import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.net.Socket; import flash.utils.ByteArray; import flash.utils.Endian; import flash.utils.setTimeout; /** * ... * @author me */ public class connection { private static const SERVER_URL:String = "localhost"; private static const PORT:int = 10002; private static var ip:int = 1; private static var _instance:connection; private var _socket:Socket; private static const checkNum:uint = 0; public function connection() { if (_instance) { throw new Error("Single"); } initSocket(); } public function initSocket():void { if (_socket == null) { _socket = new Socket(SERVER_URL, PORT); _socket.timeout = 2000; _socket.addEventListener(IOErrorEvent.IO_ERROR, onError); _socket.addEventListener(ProgressEvent.SOCKET_DATA, onProgress); } } public function connectServer():void { if (_socket.connected == false) { _socket.connect(SERVER_URL, PORT); } else { trace("has connected the server"); } } public function read():void { connectServer(); } public function write(bytes:ByteArray):void { connectServer(); _socket.writeUnsignedInt(ip++); // _socket.writeDouble(10.444); _socket.writeUnsignedInt(4355); if (bytes) { _socket.writeBytes(bytes, 0, bytes.length); } _socket.writeMultiByte("Hello Java啊啊", "GBK"); _socket.flush(); } private function onError(e:Event):void { trace(e.type + ", " + e.toString()); } private function onProgress(e:ProgressEvent):void { //setTimeout(deal, 0.00000000000000000000000000000000000000000000000000001); deal(); } private function deal():void { var index:int = -1; if (_socket.bytesAvailable >= 30) { //dealString(); index = _socket.readUnsignedInt(); ondeal(index); } } private function ondeal(index:int):void { trace("Send to client --> " + index); var cmd:int = _socket.readUnsignedInt(); trace("cmd -----> " + cmd); switch(index) { case 1: break; case 2: var len:int = _socket.bytesAvailable; len = _socket.readUnsignedInt(); trace("服务器发的包的长度-- > " + len); var bytes:ByteArray = getByteArray(); _socket.readBytes(bytes, 0, len); var str:String = bytes.readMultiByte(len, "GBK"); bytes.position = 0; trace(str); break; } } private function dealString():void { var i:int = _socket.bytesAvailable; var str:String = ""; while (i-- > 0) { var value:int; value = _socket.readByte(); if (value != 0) { str += String.fromCharCode(value); } } trace(str); } private function getByteArray():ByteArray { var byteArray:ByteArray = new ByteArray(); byteArray.endian = Endian.LITTLE_ENDIAN; byteArray.position = 0; return byteArray; } public function get socket():Socket { return _socket; } static public function get instance():connection { if (_instance == null) { _instance = new connection(); } return _instance; } } }
Java服务器端的代码如下:
package test; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; public class SocketExample { public static final int PROT = 10002; private static ServerSocket serverSocket; private static Socket socket; private static DataInputStream input; private static DataOutputStream output; @SuppressWarnings("unused") private static OutputStreamWriter outputStreamWriter; private static InputStreamReader inputStreamReader; private static char[] bytes = new char[1024 * 3]; public static void main(String[] args) throws IOException { SocketExample example = new SocketExample(); example.initSocket(); example.read(); } private void initSocket() throws IOException { serverSocket = new ServerSocket(PROT); System.out.println("start: " + serverSocket); socket = serverSocket.accept(); input = new DataInputStream(socket.getInputStream()); output = new DataOutputStream(socket.getOutputStream()); outputStreamWriter = new OutputStreamWriter(output, "GBK"); inputStreamReader = new InputStreamReader(input, "GBK"); } private void read() throws IOException { while (true) { try { try { int cmd = input.readInt(); System.out.println("As3 send a CMD number: " + cmd); double i = input.readDouble(); System.out.println(i); int j = input.readInt(); System.out.println(j); int len = inputStreamReader.read(bytes, 0, 100); String string = "-->"; string += new String(bytes, 0, len); System.out.println(string); write(2, "Hello as3 你好啊啊\n你大爷的啊啊啊".getBytes("GBK"), cmd); output.flush(); } catch (Exception e) { // TODO: handle exception } finally { // socket.close(); } } catch (Exception e) { // TODO: handle exception } finally { // serverSocket.close(); } } } private void write(int index, byte bytes[], int cmd) throws IOException { System.out.println("Send to client --> " + index); output.writeInt(index); output.writeInt(cmd); // output.flush(); switch (index) { case 1: break; case 2: if (bytes != null) { output.writeInt(bytes.length); System.out.println("发送的数据包长度--> " + bytes.length); output.write(bytes); // output.flush(); } break; default: break; } output.flush(); } @SuppressWarnings("unused") private void closeSocket() throws IOException { serverSocket.close(); socket.close(); } }
刚开始的时候as3读取包的时候直接readInt()等读的,遇到了一些莫名其妙的问题,不是遇到文件尾,就是读出了一系列乱七八糟的数据,但是调用setTimeout过段时间再读的话,不管这个时间有多小,例如上面的0....1,都会读取正确。后来断点看了一下,每次读的时候_socket的bytesAvailable即服务器发的包长度在不断的变化,很多情况下都是比服务器发的长度小,这样用字节流读取的话肯定就会遇到文件尾的错误了。因此在as3 Socket通信中读取服务器数据的时候一定要验证服务器包的完整性,即在代码中:
if (_socket.bytesAvailable >= 30) { //dealString(); index = _socket.readUnsignedInt(); ondeal(index); }
当客户端收到的包的长度 >= 服务器所发的包的长度时, 再读取一次, 而不是一收到数据就立即读取。 但是相反的是, Java代码可以直接读取的, 为什么是这样暂时没有搞清楚, 看来还是要仔细学习一下TCP / IP通信。 究其原因, 应该是AS3每收到一次服务器发的数据, 即一串二进制流吧, 就会派发ProgressEvent.SOCKET_DATA事件, 但同一时间收到的并不是一个完整的通信包, 而只是一部分, 大概就相当于加载进度条了, 每加载一部分就会派发事件, 而不是加载完成才派发, 加载完成派发Event.COMPLETED事件
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2300
- 用户1336
- 访客10722748
每日一句
All things in their being are good for something.
天生我材必有用。
天生我材必有用。
新会员