在3G上,Flash到Java套接字丢失了数据包

时间:2013-12-05 22:26:02

标签: java flash flex sockets 3g

我正在尝试使用套接字将Flash安卓应用程序与java进行通信,但当应用程序通过3G连接时 - 许多程序包丢失(未收到)。

这是我的Java服务器:

public class SServer implements Runnable  {

protected int          serverPort   = 9070;
protected ServerSocket serverSocket = null;
protected boolean      isStopped    = false;
protected List<ClientRunnable> clients = new ArrayList<ClientRunnable>();
protected int msgCounter = 0;

public static void main(String args[]) {
    SServer server = new SServer();
    new Thread(server).start();
}

public void run(){

    //init spam timer
    new Timer().schedule(new TimerTask() {              
        @Override
        public void run() {
            for (ClientRunnable cr : clients) {
                cr.send("Message " + msgCounter++);
                cr.send("Message " + msgCounter++);
                cr.send("Message " + msgCounter++);
            }       
        }
    }, 0, 2000);

    openServerSocket();
    while(! isStopped()){
        Socket clientSocket = null;
        try {
            clientSocket = this.serverSocket.accept();
        } catch (IOException e) {
            if(isStopped()) {
                System.out.println("Server Stopped."); return;
            }
            throw new RuntimeException("Error accepting client connection", e);
        }
        ClientRunnable cr = new ClientRunnable(clientSocket);
        clients.add(cr);
        new Thread(cr).start();
    }
    System.out.println("Server Stopped.") ;
}

private synchronized boolean isStopped() {
    return this.isStopped;
}


private void openServerSocket() {
    try {
        this.serverSocket = new ServerSocket(this.serverPort);
        System.out.println("Server Started.") ;
    } catch (IOException e) {
        throw new RuntimeException("Cannot open port 8080", e);
    }
}

}

这是客户端主题:

public class ClientRunnable implements Runnable{

protected Socket clientSocket = null;
protected Boolean connected = false;
protected BufferedReader in = null;
protected PrintStream os = null;


public ClientRunnable(Socket clientSocket) {
    this.clientSocket = clientSocket;
}

public void run() {

    connected = true;

    try {
        //InputStream input  = clientSocket.getInputStream();
        in = new BufferedReader (new InputStreamReader(clientSocket.getInputStream(), "UTF-8" ));
        os = new PrintStream(clientSocket.getOutputStream());

        //read
        //..


    } catch (IOException e) {
        onError(e);
        connected = false;
        closeConnection();
    } 
}

private void closeConnection() {
    os.close();
    //other closing code..
}

public void send(String data) {
    try {
        byte[] dataBytes = data.getBytes("UTF-8");
        //will contain all bytes plus zery byte flash delimiter
        byte[] allBytes = new byte[dataBytes.length + 1];
        System.arraycopy(dataBytes, 0, allBytes, 0, dataBytes.length);
        allBytes[allBytes.length-1] = (byte)0;
        synchronized (this) {
            Thread.sleep(50); //non 3G workaround
            os.write(allBytes);
            os.flush();
        }
    } catch (Exception e) {
        e.printStackTrace();
         onError(e);
    } 
}

public void onError(Exception ex) {
    ex.printStackTrace();
}

}

请注意Thread.sleep(50);在每次发送写入之前 - 修复非常规非3G连接上的问题。但是当应用程序在3G上运行时,这个值必须要高得多,并且有时候仍然会错过pachages。

这是我的flex客户端:

<?xml version="1.0" encoding="utf-8"?>

<fx:Script>
    <![CDATA[
        import spark.events.ViewNavigatorEvent;

        private var _socket:Socket;
        private var _host:String = "<MY HOST IP>";
        private var _port:int = 9070;

        protected function onViewActivate(event:ViewNavigatorEvent):void {
            _socket = new Socket(_host, _port);
            _socket.addEventListener(Event.CLOSE, function(e:Event):void{ ta.appendText("Close\n"); });
            _socket.addEventListener(Event.CONNECT, function(e:Event):void{ ta.appendText("Connect\n"); });
            _socket.addEventListener(IOErrorEvent.IO_ERROR, function(e:IOErrorEvent):void{ ta.appendText("IO Error\n"); });
            _socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function(e:IOErrorEvent):void{ ta.appendText("Security Error\n"); });
            _socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
        }

        private function socketDataHandler(event:ProgressEvent):void {
            var socket:Socket = event.target as Socket;
            var str:String = socket.readUTFBytes(socket.bytesAvailable);
            ta.appendText(str+"\n");
        }

    ]]>
</fx:Script>

<s:VGroup width="100%" height="100%">
    <s:TextArea id="ta" skinClass="spark.skins.mobile.TextAreaSkin" width="100%" height="100%" />
    <s:Button label="Reconnect" click="_socket.connect(_host, _port)" />
</s:VGroup>

这就是它最终的样子: (请注意,排序的发送是有问题的,尽管有50ms的延迟)

enter image description here

正如您所看到的,未收到许多顺序消息。增加延迟有助于但不总是(并且作为解决方案很糟糕)。

Flex项目已上传HERE

Java项目已上传HERE

1 个答案:

答案 0 :(得分:1)

我最近在AS和Java之间运行的套接字连接上遇到了类似的问题。我通过在Java中创建消息队列,在消息中添加消息ID,然后在发送队列中的下一条消息之前使ActionScript端使用messageID进行响应来解决它。这保证了同样的消息反复出现,直到AS回应得到它。