一门好的语言需要良好的支持IO操作, Java有了Socket才有了JDBC, Servlet, Tomcat and etc.
先看下FLEX的XMLSocket.
XMLSocket提供的接口比较简单, 文档还有简单的例子, 跟Java区别写法比较大的就是它异步的回调.
FLASH客户端代码:
- 一门好的语言需要良好的支持IO操作, Java有了Socket才有了JDBC, Servlet, Tomcat and etc.
- 先看下FLEX的XMLSocket.
- XMLSocket提供的接口比较简单, 文档还有简单的例子, 跟Java区别写法比较大的就是它异步的回调.
- <?xml version="1.0" encoding="utf-8"?>
- <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="800" height="600" creationComplete="initApp()">
- <mx:Script><![CDATA[
- import mx.controls.Alert;
- private var sock:XMLSocket = null;
- //Initial the GUI
- private function initApp():void {
- }
- //Click logon
- private function connectServer(event:MouseEvent):void {
- if (this.sock != null)
- return;
- this.sock = new XMLSocket();
- //Refer to XMLSocket document, follow the sample here
- this.configureListeners(this.sock);
- this.sock.connect("localhost", 8080);
- this.sendButton.enabled = true;
- }
- public function send(data:Object):void {
- this.sock.send(data);
- }
- private function configureListeners(dispatcher:IEventDispatcher):void {
- dispatcher.addEventListener(Event.CLOSE, closeHandler);
- dispatcher.addEventListener(Event.CONNECT, connectHandler);
- dispatcher.addEventListener(DataEvent.DATA, dataHandler);
- dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
- dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
- dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
- }
- private function closeHandler(event:Event):void {
- trace("closeHandler: " + event);
- this.appendLine("CLose event socket");
- }
- private function connectHandler(event:Event):void {
- trace("connectHandler: " + event);
- this.appendLine("Send: connect to server sucessfully." + event.target.toLocaleString());
- }
- private function appendLine(mesg:String):void {
- //The /0 will be added automatically like C
- this.messageArea.text += (mesg);
- }
- private function dataHandler(event:DataEvent):void {
- trace("dataHandler: " + event);
- this.appendLine("Server Response:" + event.data);
- //this.messageArea.text += ("Server Response:" + event.target.toLocaleString() + "/r/n");
- }
- private function ioErrorHandler(event:IOErrorEvent):void {
- trace("ioErrorHandler: " + event);
- this.appendLine("Oops, ioError");
- }
- private function progressHandler(event:ProgressEvent):void {
- trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
- }
- private function securityErrorHandler(event:SecurityErrorEvent):void {
- trace("securityErrorHandler: " + event);
- this.appendLine("Oops, encounter security error:" + event.text);
- }
- private function sendMessage(event:MouseEvent):void {
- var message:String = this.messageField.text;
- //message = "<message>" + message + "</message>/r/n";
- message = message + "/r/n";
- if (message != null && message.length > 0) {
- this.send(message);
- //this.messageArea.text += ("Send:" + message + "/r/n");
- this.appendLine("Send:" + message );
- }
- }
- ]]>
- </mx:Script>
- <mx:TextArea x="10" y="10" width="780" height="386" id="messageArea"/>
- <mx:TextInput x="10" y="416" width="536" height="31" id="messageField"/>
- <mx:Button x="577" y="416" label="Send" height="31" width="69" id="sendButton" enabled="false" click="sendMessage(event)"/>
- <mx:Button x="669" y="416" label="Logon" height="31" id="logonButton" click="connectServer(event)"/>
- </mx:Application>
JAVA服务器:
- /*
- * testflex.CellPhoneLocator.java 2008-12-23
- */
- package testflex;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.PrintWriter;
- import java.io.UnsupportedEncodingException;
- import java.net.InetAddress;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.StringTokenizer;
- /**
- * The demo provided to test the flash XMLSocket
- * @author zealvampire
- * @version 1.0 2008-12-23
- */
- public class CellPhoneLocator {
- /** The listening port of server. */
- private int serverPort = 8080;
- private int backlog = 50;
- private InetAddress bindAddress = null;
- private Map<String,String> questions = new HashMap<String,String>(5);
- private boolean toStopServer = false;
- //Open 843 to handle the policy request.
- private PolicyService policyService = null;
- /** The server socket */
- private ServerSocket serverSocket = null;
- public CellPhoneLocator() {
- questions.put("130", "130's from chinaunicom");
- questions.put("131", "131's from chinaunicom");
- questions.put("133", "133's from Chinatelecom");
- questions.put("135", "135's from China Mobile");
- questions.put("138", "138's from China Mobile");
- }
- private String locateNumber(String phoneNum) {
- String location = this.questions.get(phoneNum);
- return location==null ? (phoneNum + "'s Unknown") : location;
- }
- private class FlexStringReader extends InputStreamReader {
- private StringBuffer buf = new StringBuffer();
- public FlexStringReader(InputStream in) {
- super(in);
- }
- public FlexStringReader(InputStream in, String charsetName) throws UnsupportedEncodingException {
- super(in, charsetName);
- }
- //Make sure it works.
- public String readLine() throws IOException {
- int oneChar = 0;
- buf.setLength(0);
- while ((oneChar = this.read()) != -1) {
- if (oneChar == '/0')
- break;
- buf.append((char) oneChar);
- }
- return buf.toString();
- }
- }
- private class RequestHanlder implements Runnable {
- private Socket sock = null;
- public RequestHanlder(Socket pSock) {
- this.sock = pSock;
- }
- private String command = "";
- private String parameter = "";
- public void run() {
- FlexStringReader reader = null;
- PrintWriter pw = null;
- String line = null;
- try {
- System.out.println("Client:" + this.sock);
- InputStream in = this.sock.getInputStream();
- reader = new FlexStringReader(in, "UTF-8");
- pw = new PrintWriter(this.sock.getOutputStream());
- String policyRequest = reader.readLine();//new String(headers);
- //FLash client will open two ports, one to retrieve the policy.
- //Another to normal communicate to server.
- if (policyRequest.startsWith("<policy-file-request/>")) {
- pw.write("<?xml version=/"1.0/"?><cross-domain-policy><site-control permitted-cross-domain-policies=/"all/"/><allow-access-from domain=/"*/" to-ports=/"*/" /></cross-domain-policy>/0");
- pw.flush();
- System.out.println("Policy's sent by current listening port:" + serverPort);
- Thread.sleep(10000);
- throw new IOException("A dirty return, never follow it dude.");
- }
- else {
- pw.write("Hi " + this.sock + ",at your service, send me the cell phone please./0");
- }
- pw.flush();
- while ((line = reader.readLine()).length() > 0) {
- this.parseRequest(line);
- if ("where".equalsIgnoreCase(command)) {
- pw.write(locateNumber(this.parameter)+ '/0');
- pw.flush();
- }
- else if ("quit".equalsIgnoreCase(command) || "exit".equalsIgnoreCase(command)) {
- break;
- }
- else {
- pw.write("Oops, unknown command./0");
- pw.flush();
- }
- }
- }
- catch (IOException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- finally {
- //FIXME, try to close the I/O stream
- try {
- sock.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- private void parseRequest(String line) {
- command = "";
- parameter = "";
- StringTokenizer tokens = new StringTokenizer(line, " /t/n/r/f/0", false);
- int count = tokens.countTokens();
- if (count > 0) {
- this.command = tokens.nextToken();
- if (count > 1)
- this.parameter = tokens.nextToken();
- }
- System.out.println("Command=" + this.command + "/tParameter=" + this.parameter);
- }
- }
- /**
- * Start the server first.
- * @throws IOException
- */
- public void startServer() throws IOException {
- this.serverSocket = new ServerSocket(serverPort, backlog, bindAddress);
- System.out.println(new Date() + ": Starting server.");
- //The policy swith
- this.policyService = new PolicyService();
- this.policyService.start();
- }
- private class PolicyService extends Thread {
- private ServerSocket policySock = null;
- public void run() {
- try {
- this.policySock = new ServerSocket(843);
- System.out.println(new Date() + ":The policy server is running on 843......");
- Socket sock = null;
- String request = null;
- FlexStringReader br = null;
- PrintWriter pw = null;
- //FIXME, create another thread to handle the request.
- while ((sock = this.policySock.accept()) != null) {
- br = new FlexStringReader(sock.getInputStream());
- pw = new PrintWriter(sock.getOutputStream());
- System.out.println("Policy server:client socket=" + sock);
- request = br.readLine();
- System.out.println("Policy service: request=" + request);
- if (request.startsWith("<policy-file-request/>")) {
- pw.write("<?xml version=/"1.0/"?><cross-domain-policy><site-control permitted-cross-domain-policies=/"all/"/><allow-access-from domain=/"*/" to-ports=/"*/" /></cross-domain-policy>/0");
- pw.flush();
- System.out.println("Policy service:Policy file's sent......");
- //Wait until the xml's pushed to client.
- Thread.sleep(10000);
- }
- //FIXME, not a good way the release resources.
- System.out.println("Policy service: close the client socket.");
- br.close();
- pw.close();
- sock.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally {
- //FIXME, refactor it ..
- if (this.policySock != null) {
- try {
- this.policySock.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
- /**
- * Service's running
- * @throws IOException
- */
- public void service() throws IOException {
- Socket clientSock = null;
- Thread handler = null;
- while (!this.toStopServer && (clientSock = this.serverSocket.accept()) != null) {
- //FIXME, only a demo, try to control the threads using producer/consumer,threadpool in your project.
- handler = new Thread(new RequestHanlder(clientSock));
- handler.start();
- }
- this.releaseResource();
- }
- public void releaseResource() {
- if (this.serverSocket != null)
- try {
- this.serverSocket.close();
- this.serverSocket = null;
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- /**
- * @param args
- */
- public static void main(String[] args) {
- CellPhoneLocator server = new CellPhoneLocator();
- try {
- server.startServer();
- server.service();
- } catch (IOException e) {
- e.printStackTrace();
- server.releaseResource();
- }
- }
- /**
- * @return the serverPort
- */
- public int getServerPort() {
- return serverPort;
- }
- /**
- * @param serverPort the serverPort to set
- */
- public void setServerPort(int serverPort) {
- this.serverPort = serverPort;
- }
- }
麻烦的只是权限, 因为flash player只相信一个原则, SWF从哪里来, 它就相信哪个域; 也就是说SWF本地运行还有从网络下载到浏览器它的采访权限是完全不一样的, SANDBOX沙漏这个限制就好像java applet一样. 我们需要设置好policy.
1. 在本地Flash player运行, I mean 直接点击生成的SWF
不需要设置, XMLSocket可以直接发送接受服务器的信息. 不过我这里用的都是localhost, 不知道使用外部IP会如何..不确定.
2. SWF放在web 服务器下, 使用浏览器采访
(1)默认先连XMLSocket目标服务器的843端口, 发送<policy-file-request/>/0 类似这样的信息.
我们返回"<?xml version=/"1.0/"?><cross-domain-policy><site-control permitted-cross-domain-policies=/"all/"/><allow-access-from domain=/"*/" to-ports=/"*/" /></cross-domain-policy>/0"
(2) 如1失败, 则查看AS中是否
Security.loadPolicyFile( "xmlsocket://host:port" ) 有则尝试加载crossdomain.xml
(3)2失败则只能链XMLSocket的目标端口了. 还失败就不可能建立连接了.
3.需要注意的是XMLSocket未必一定要发送XML, 你也可以直接发送String, 但是flex里面的string发送过去是以/0结束的.
后台需要额外处理一下/0; 返回到flash的字符串也必须使用/0才能在在客户端接收到. 冇办法, 每个语言都有自己的规则.
private function dataHandler(event:DataEvent):void {
trace("dataHandler: " + event);
this.appendLine("Server Response:" + event.data);
//this.messageArea.text += ("Server Response:" + event.target.toLocaleString() + "/r/n");
}
之后会继续测试一下Flex 的binary socket和其他IO