java as3 socket_As3 Socket通信

最近研究了下as3 Socket 跟Java服务器的通信,一些心得分享下。

客户端的代码如下:

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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值