【服务器端】
JDK1.6,“java.net”包对网络编程提供了非常全面的支持,包括Socket
开发环境:Eclipse
【客户端】
Flex4,”flash.net”包也提供了Socket的支持
开发环境:FlashBuilder4
?
我是用Java启动一个ServerSocket作为服务器,Flex创建一个页面,当点击页面上的按钮时向Java服务器发送消息。
?
Flex客户端输入“阿里巴巴”再点击按钮:
?Java控制台:
?
?
Flex项目分为两种:一种是普通的本地项目,也就是不依赖其它服务器;另一种是远程服务器项目,这需要依赖其它语言的服务器容器。如果是普通的本地项目,Socket通信是非常容易的,但是如果是远程项目,Socket通信需要考虑Flex安全沙箱问题,后面会详细介绍。
?
?
编写Socket Server代码的步骤通常是:
①创建ServerSocket,定义服务端口号
②使用ServerSocket.accept()监听socket请求,如果有请求会创建一个Socket对象
③通过socket.getInputStream()获取客户端的请求数据
④通过socket.getOutputStream()向客户端返回数据
⑤通过socket.close()结束本次会话
按照上面的步骤,如果有多个客户端向服务器发送请求的话,服务器只会处理第一个请求,其它请求会排队等待,只有第一个请求执行socket.close的时候下一个客户端请求才会运行。为了实现多客户端并发请求,在第②步后面需要建立多线程。
?
废话不多说,直接代码说明。
?
首先创建一个
SocketUtil类,用于创建ServerSocket和获取Socket
-
public?class?SocketUtil?{ ??
- ???? ??
- ?????
-
?
-
?
-
?
-
??
- ????public?static?ServerSocket?getServerSocket(int?port){ ??
- ????????ServerSocket?server?=?null; ??
- ????????try?{ ??
- ????????????server?=?new?ServerSocket(port); ??
- ????????????System.out.println("------ServerSocket创建成功,Port:"+port); ??
- ????????????return?server; ??
- ????????}?catch?(IOException?e)?{ ??
- ????????????if(server!=null?&&?!server.isClosed()){ ??
- ????????????????try?{ ??
- ????????????????????server.close(); ??
- ????????????????}?catch?(IOException?e1)?{ ??
- ????????????????????e1.printStackTrace(); ??
- ????????????????} ??
- ????????????} ??
- ????????????throw?new?RuntimeException("创建ServerSocket时发生异常,Port:"+port,e); ??
- ????????} ??
- ????} ??
- ???? ??
- ?????
-
?
-
?
-
?
-
??
- ????public?static?Socket?getSocket(ServerSocket?server){ ??
- ????????Socket?socket?=?null; ??
- ????????try?{ ??
- ????????????socket?=?server.accept(); ??
- ????????????System.out.println("------Socket连接成功,IP:"+socket.getInetAddress()); ??
- ????????????return?socket; ??
- ????????}?catch?(IOException?e)?{ ??
- ????????????if(socket!=null?&&?!socket.isClosed()){ ??
- ????????????????try?{ ??
- ????????????????????socket.close(); ??
- ????????????????}?catch?(IOException?e1)?{ ??
- ????????????????????e1.printStackTrace(); ??
- ????????????????} ??
- ????????????} ??
- ????????????throw?new?RuntimeException("创建Socket时发送异常",e); ??
- ????????} ??
- ????} ??
- ???? ??
- }??
?
然后创建一个带多线程的类,用于服务器与客户端的IO通信
-
public?class?SocketThread?implements?Runnable?{ ??
- ????private?Socket?socket; ??
- ????private?String?encoding; ??
- ???? ??
- ????public?SocketThread(Socket?socket,String?encoding)?{ ??
- ????????this.socket?=?socket; ??
- ????????this.encoding?=?encoding; ??
- ????} ??
- ???? ??
- ?????
-
?
-
??
- ????@Override??
- ????public?void?run()?{ ??
- ????????try?{ ??
- ????????????BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(socket ??
- ????????????????????.getInputStream(),?encoding)); ??
- ????????????BufferedWriter?bw?=?new?BufferedWriter(new?OutputStreamWriter( ??
- ????????????????????socket.getOutputStream(),?encoding)); ??
- ???????????? ??
- ????????????String?getMsg; ??
- ????????????while?((getMsg?=?br.readLine())?!=?null?&&?!"exit".equalsIgnoreCase(getMsg))?{ ??
- ??????????????????
- ????????????????System.out.println("From?client?message:"?+?getMsg); ??
- ????????????????bw.append("你好["?+?socket.getInetAddress()?+?"],服务器收到你的信息:"??
- ????????????????????????+?getMsg?+?"rn"); ??
- ????????????????bw.flush(); ??
- ????????????} ??
- ???????????? ??
- ??????????????
- ????????????br.close(); ??
- ????????????bw.close(); ??
- ????????????socket.close(); ??
- ????????????System.out.println("当前Socket连接结束......"); ??
- ????????}?catch?(Exception?e)?{ ??
- ????????????if(!socket.isClosed()){ ??
- ????????????????try?{ ??
- ????????????????????socket.close(); ??
- ????????????????}?catch?(IOException?e1)?{ ??
- ????????????????????e1.printStackTrace(); ??
- ????????????????} ??
- ????????????} ??
- ????????????throw?new?RuntimeException("Socket线程类发送异常...",e); ??
- ????????} ??
- ????} ??
- }??
?
最后在Main函数中启动Socket服务即可:
-
public?static?void?main(String[]?args)?{ ??
- ????????new?SocketServer().startSocket(); ??
- ????}??
?
Flex端创建Socket有两种方式:
第一种通过connect方法连接Socket服务器:
- var?socket:Socket?=?new?Socket(); ??
- socket.connect("localhost",10086);??
?第二种通过创建Socket实例时在构造函数中传入服务器ip和端口号连接:
- socket?=?new?Socket("localhost",10086);??
?Flex通过ByteArray传送IO数据,这里有一点稍微注意一下在写入的内容后面会加"
rn"回车换行符,因为java端是通过BufferedReader.readLine的形式获取一行数据,如果不换行服务器端IO就一直处于阻塞状态:
-
??
- var?message:ByteArray?=?new?ByteArray(); ??
-
??
- message.writeUTFBytes(txt_socket.text+"rn"); ??
-
??
- socket.writeBytes(message);??
?Flex有多种事件用于监听Socket的状态:
- Event.CONNECT:Socket与服务器成功连接时触发的事件 ??
- Event.CLOSE:Socket与服务器断开连接时触发的事件 ??
- IOErrorEvent.IO_ERROR:Socket通信时发生IO错误时触发的事件 ??
- ProgressEvent.SOCKET_DATA:服务器返回数据时触发的事件??
?
新建一个Flex普通项目,入口文件定义为index.mxml,在mxml文件中新建一个textinput文本框用于获取用户输入的内容,button按钮用户发送内容到java socket服务器,一个label用户显示向前socket状态,另一个label用于显示从服务器返回的信息。 index.mxml代码如下:
-
<s:Application?xmlns:fx="http://ns.adobe.com/mxml/2009"? ??
- ???????????????xmlns:s="library://ns.adobe.com/flex/spark"? ??
- ???????????????xmlns:mx="library://ns.adobe.com/flex/mx"?minWidth="955"?minHeight="600">??
- ??
- ????<fx:Script>??
- ????????<![CDATA[??
-
??????????????
-
??????????????
-
????????????private?var?socket:Socket?=?null;??
-
????????????protected?function?button1_clickHandler(event:MouseEvent):void??
-
????????????{??
-
????????????????if(socket==null?||?!socket.connected){??
-
????????????????????//连接服务器(ip,port)??
-
????????????????????socket?=?new?Socket("localhost",10086);??
-
??????????????????????
-
????????????????????//成功连接状态事件??
-
????????????????????socket.addEventListener(Event.CONNECT,function?connFun(e:Event):void{??
-
????????????????????????l_status.text?=?"Connect?to?server?success...";??
-
????????????????????});??
-
????????????????????//连接中断事件??
-
????????????????????socket.addEventListener(Event.CLOSE,function?closeFun(e:Event):void{??
-
????????????????????????l_status.text?=?"Connect?to?server?closed...";??
-
????????????????????});??
-
????????????????????//连接异常事件??
-
????????????????????socket.addEventListener(IOErrorEvent.IO_ERROR,function?closeFun(e:IOErrorEvent):void{??
-
????????????????????????l_status.text?=?"Connect?exception?..."+e.toString();??
-
????????????????????});??
-
????????????????????//服务器信息事件??
-
????????????????????socket.addEventListener(ProgressEvent.SOCKET_DATA,function?dataFun(e:ProgressEvent):void{??
-
????????????????????????var?getMsg:ByteArray?=?new?ByteArray;??
-
????????????????????????socket.readBytes(getMsg);??
-
????????????????????????l_result.text?=?getMsg.toString();??
-
????????????????????});??
-
????????????????}??
-
??????????????????
-
????????????????//ByteArray存放数据??
-
????????????????var?message:ByteArray?=?new?ByteArray();??
-
????????????????//使用UTF形式防止中文乱码??
-
????????????????message.writeUTFBytes(txt_socket.text+"rn");??
-
????????????????//数据写入缓冲区??
-
????????????????socket.writeBytes(message);??
-
????????????????//将缓冲区数据发送出去??
-
????????????????socket.flush();??
-
????????????????//清空文本框内容??
-
????????????????txt_socket.text?=?"";??
-
????????????}??
-
????????]]>??
- ????</fx:Script>??
- ??
- ????<fx:Declarations>??
- ??????????
- ????</fx:Declarations>??
- ????<s:Button?x="156"?y="56"?label="按钮"?click="button1_clickHandler(event)"/>??
- ????<s:TextInput?x="20"?y="56"?id="txt_socket"/>??
- ????<s:Label?x="20"?y="104"?id="l_status"/>??
- ????<s:Label?x="234"?y="65"?id="l_result"/>??
-
</s:Application>??
?
代码编写完成后运行index.mxml文件,最后执行效果就如前面【实例效果】所示。
?
?
下面这段是从网上抄的:
----------------------------------------------------------------------------
在 Adobe Flash Player 升级到 9.0.124 后,由于安全策略更改,原来 Socket 或 XmlSocket 的应用里的 http 方式加载安全策略的手段不能继续使用。更改如下:
1,首先检测目标服务器的 843 端口是否提供安全策略?
2,如果 1 没有检测到策略,则检测 actionscript 是否使用了 Security.loadPolicyFile(xmlsocket://)手段提供安全策略,如果还没检测到,则使用第 3 步检测
3,检测目标服务器目标端口是否提供安全策略。
在说具体处理方式前,我先描述一下 Flash Player 的验证过程。在 Flex 程序发出 Socket 或 XmlSocket( 以下统称为 Socket) 请求前, FlashPlayer 会先判断是否为本地调用,如果不是。即用一个 Socket 去链接到你的服务端,三次握手成功后一方面发出字符串“ <policy-file-request/>