我正在尝试使用套接字将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的延迟)
正如您所看到的,未收到许多顺序消息。增加延迟有助于但不总是(并且作为解决方案很糟糕)。
Flex项目已上传HERE
Java项目已上传HERE
答案 0 :(得分:1)
我最近在AS和Java之间运行的套接字连接上遇到了类似的问题。我通过在Java中创建消息队列,在消息中添加消息ID,然后在发送队列中的下一条消息之前使ActionScript端使用messageID进行响应来解决它。这保证了同样的消息反复出现,直到AS回应得到它。