加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Flex通信-与Java实现Socket通信实例

发布时间:2020-12-15 03:51:55 所属栏目:百科 来源:网络整理
导读:Flex通信-与Java实现Socket通信实例 ? 转自:http://blessht.iteye.com/blog/1136888 博客分类: Flex 环境准备 【服务器端】 JDK1.6,“java.net”包对网络编程提供了非常全面的支持,包括Socket 开发环境:Eclipse 【客户端】 Flex4,”flash.net”包也提

Flex通信-与Java实现Socket通信实例? 转自:http://blessht.iteye.com/blog/1136888

博客分类:

  • Flex
  • 环境准备
【服务器端】
JDK1.6,“java.net”包对网络编程提供了非常全面的支持,包括Socket
开发环境:Eclipse
【客户端】
Flex4,”flash.net”包也提供了Socket的支持
开发环境:FlashBuilder4
?
  • 实例效果
我是用Java启动一个ServerSocket作为服务器,Flex创建一个页面,当点击页面上的按钮时向Java服务器发送消息。
?
Flex客户端输入“阿里巴巴”再点击按钮:


?Java控制台:


?
?
  • 注意事项
Flex项目分为两种:一种是普通的本地项目,也就是不依赖其它服务器;另一种是远程服务器项目,这需要依赖其它语言的服务器容器。如果是普通的本地项目,Socket通信是非常容易的,但是如果是远程项目,Socket通信需要考虑Flex安全沙箱问题,后面会详细介绍。


?
?
  • Java Socket服务器
编写Socket Server代码的步骤通常是:
①创建ServerSocket,定义服务端口号
②使用ServerSocket.accept()监听socket请求,如果有请求会创建一个Socket对象
③通过socket.getInputStream()获取客户端的请求数据
④通过socket.getOutputStream()向客户端返回数据
⑤通过socket.close()结束本次会话
按照上面的步骤,如果有多个客户端向服务器发送请求的话,服务器只会处理第一个请求,其它请求会排队等待,只有第一个请求执行socket.close的时候下一个客户端请求才会运行。为了实现多客户端并发请求,在第②步后面需要建立多线程。
?
废话不多说,直接代码说明。
?
首先创建一个 SocketUtil类,用于创建ServerSocket和获取Socket
Java代码??
  1. public?class?SocketUtil?{ ??
  2. ???? ??
  3. ????/**??
  4. ?????*?创建ServerSocket??
  5. ?????*?@param?port??
  6. ?????*?@return??
  7. ?????*/??
  8. ????public?static?ServerSocket?getServerSocket(int?port){ ??
  9. ????????ServerSocket?server?=?null; ??
  10. ????????try?{ ??
  11. ????????????server?=?new?ServerSocket(port); ??
  12. ????????????System.out.println("------ServerSocket创建成功,Port:"+port); ??
  13. ????????????return?server; ??
  14. ????????}?catch?(IOException?e)?{ ??
  15. ????????????if(server!=null?&&?!server.isClosed()){ ??
  16. ????????????????try?{ ??
  17. ????????????????????server.close(); ??
  18. ????????????????}?catch?(IOException?e1)?{ ??
  19. ????????????????????e1.printStackTrace(); ??
  20. ????????????????} ??
  21. ????????????} ??
  22. ????????????throw?new?RuntimeException("创建ServerSocket时发生异常,Port:"+port,e); ??
  23. ????????} ??
  24. ????} ??
  25. ???? ??
  26. ????/**??
  27. ?????*?获取Socket??
  28. ?????*?@param?server??
  29. ?????*?@return??
  30. ?????*/??
  31. ????public?static?Socket?getSocket(ServerSocket?server){ ??
  32. ????????Socket?socket?=?null; ??
  33. ????????try?{ ??
  34. ????????????socket?=?server.accept(); ??
  35. ????????????System.out.println("------Socket连接成功,IP:"+socket.getInetAddress()); ??
  36. ????????????return?socket; ??
  37. ????????}?catch?(IOException?e)?{ ??
  38. ????????????if(socket!=null?&&?!socket.isClosed()){ ??
  39. ????????????????try?{ ??
  40. ????????????????????socket.close(); ??
  41. ????????????????}?catch?(IOException?e1)?{ ??
  42. ????????????????????e1.printStackTrace(); ??
  43. ????????????????} ??
  44. ????????????} ??
  45. ????????????throw?new?RuntimeException("创建Socket时发送异常",e); ??
  46. ????????} ??
  47. ????} ??
  48. ???? ??
  49. }??
?
然后创建一个带多线程的类,用于服务器与客户端的IO通信
Java代码??
  1. public?class?SocketThread?implements?Runnable?{ ??
  2. ????private?Socket?socket; ??
  3. ????private?String?encoding; ??
  4. ???? ??
  5. ????public?SocketThread(Socket?socket,String?encoding)?{ ??
  6. ????????this.socket?=?socket; ??
  7. ????????this.encoding?=?encoding; ??
  8. ????} ??
  9. ???? ??
  10. ????/**??
  11. ?????*?与客户端交互代码??
  12. ?????*/??
  13. ????@Override??
  14. ????public?void?run()?{ ??
  15. ????????try?{ ??
  16. ????????????BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(socket ??
  17. ????????????????????.getInputStream(),?encoding)); ??
  18. ????????????BufferedWriter?bw?=?new?BufferedWriter(new?OutputStreamWriter( ??
  19. ????????????????????socket.getOutputStream(),?encoding)); ??
  20. ???????????? ??
  21. ????????????String?getMsg; ??
  22. ????????????while?((getMsg?=?br.readLine())?!=?null?&&?!"exit".equalsIgnoreCase(getMsg))?{ ??
  23. ????????????????//?客户端未提出"exit"命令,则循环交流???
  24. ????????????????System.out.println("From?client?message:"?+?getMsg); ??
  25. ????????????????bw.append("你好["?+?socket.getInetAddress()?+?"],服务器收到你的信息:"??
  26. ????????????????????????+?getMsg?+?"rn"); ??
  27. ????????????????bw.flush(); ??
  28. ????????????} ??
  29. ???????????? ??
  30. ????????????//客户端提出"exit"请求,关闭当前socket...???
  31. ????????????br.close(); ??
  32. ????????????bw.close(); ??
  33. ????????????socket.close(); ??
  34. ????????????System.out.println("当前Socket连接结束......"); ??
  35. ????????}?catch?(Exception?e)?{ ??
  36. ????????????if(!socket.isClosed()){ ??
  37. ????????????????try?{ ??
  38. ????????????????????socket.close(); ??
  39. ????????????????}?catch?(IOException?e1)?{ ??
  40. ????????????????????e1.printStackTrace(); ??
  41. ????????????????} ??
  42. ????????????} ??
  43. ????????????throw?new?RuntimeException("Socket线程类发送异常...",e); ??
  44. ????????} ??
  45. ????} ??
  46. }??
?
最后在Main函数中启动Socket服务即可:
Java代码??
  1. public?static?void?main(String[]?args)?{ ??
  2. ????????new?SocketServer().startSocket(); ??
  3. ????}??
?
  • Flex客户端代码
Flex端创建Socket有两种方式:
第一种通过connect方法连接Socket服务器:
Java代码?

复制代码

?

收藏代码

  1. var?socket:Socket?=?new?Socket(); ??
  2. socket.connect("localhost",10086);??
?第二种通过创建Socket实例时在构造函数中传入服务器ip和端口号连接:
Java代码??
  1. socket?=?new?Socket("localhost",10086);??
?Flex通过ByteArray传送IO数据,这里有一点稍微注意一下在写入的内容后面会加" rn"回车换行符,因为java端是通过BufferedReader.readLine的形式获取一行数据,如果不换行服务器端IO就一直处于阻塞状态:
Java代码??
  1. //ByteArray存放数据???
  2. var?message:ByteArray?=?new?ByteArray(); ??
  3. //使用UTF形式防止中文乱码???
  4. message.writeUTFBytes(txt_socket.text+"rn"); ??
  5. //数据写入缓冲区???
  6. socket.writeBytes(message);??
?Flex有多种事件用于监听Socket的状态:
Java代码??
  1. Event.CONNECT:Socket与服务器成功连接时触发的事件 ??
  2. Event.CLOSE:Socket与服务器断开连接时触发的事件 ??
  3. IOErrorEvent.IO_ERROR:Socket通信时发生IO错误时触发的事件 ??
  4. ProgressEvent.SOCKET_DATA:服务器返回数据时触发的事件??
?
新建一个Flex普通项目,入口文件定义为index.mxml,在mxml文件中新建一个textinput文本框用于获取用户输入的内容,button按钮用户发送内容到java socket服务器,一个label用户显示向前socket状态,另一个label用于显示从服务器返回的信息。 index.mxml代码如下:
Xml代码??
  1. <s:Application?xmlns:fx="http://ns.adobe.com/mxml/2009"? ??
  2. ???????????????xmlns:s="library://ns.adobe.com/flex/spark"? ??
  3. ???????????????xmlns:mx="library://ns.adobe.com/flex/mx"?minWidth="955"?minHeight="600">??
  4. ??
  5. ????<fx:Script>??
  6. ????????<![CDATA[??
  7. ??????????????
  8. ??????????????
  9. ????????????private?var?socket:Socket?=?null;??
  10. ????????????protected?function?button1_clickHandler(event:MouseEvent):void??
  11. ????????????{??
  12. ????????????????if(socket==null?||?!socket.connected){??
  13. ????????????????????//连接服务器(ip,port)??
  14. ????????????????????socket?=?new?Socket("localhost",10086);??
  15. ??????????????????????
  16. ????????????????????//成功连接状态事件??
  17. ????????????????????socket.addEventListener(Event.CONNECT,function?connFun(e:Event):void{??
  18. ????????????????????????l_status.text?=?"Connect?to?server?success...";??
  19. ????????????????????});??
  20. ????????????????????//连接中断事件??
  21. ????????????????????socket.addEventListener(Event.CLOSE,function?closeFun(e:Event):void{??
  22. ????????????????????????l_status.text?=?"Connect?to?server?closed...";??
  23. ????????????????????});??
  24. ????????????????????//连接异常事件??
  25. ????????????????????socket.addEventListener(IOErrorEvent.IO_ERROR,function?closeFun(e:IOErrorEvent):void{??
  26. ????????????????????????l_status.text?=?"Connect?exception?..."+e.toString();??
  27. ????????????????????});??
  28. ????????????????????//服务器信息事件??
  29. ????????????????????socket.addEventListener(ProgressEvent.SOCKET_DATA,function?dataFun(e:ProgressEvent):void{??
  30. ????????????????????????var?getMsg:ByteArray?=?new?ByteArray;??
  31. ????????????????????????socket.readBytes(getMsg);??
  32. ????????????????????????l_result.text?=?getMsg.toString();??
  33. ????????????????????});??
  34. ????????????????}??
  35. ??????????????????
  36. ????????????????//ByteArray存放数据??
  37. ????????????????var?message:ByteArray?=?new?ByteArray();??
  38. ????????????????//使用UTF形式防止中文乱码??
  39. ????????????????message.writeUTFBytes(txt_socket.text+"rn");??
  40. ????????????????//数据写入缓冲区??
  41. ????????????????socket.writeBytes(message);??
  42. ????????????????//将缓冲区数据发送出去??
  43. ????????????????socket.flush();??
  44. ????????????????//清空文本框内容??
  45. ????????????????txt_socket.text?=?"";??
  46. ????????????}??
  47. ????????]]>??
  48. ????</fx:Script>??
  49. ??
  50. ????<fx:Declarations>??
  51. ????????<!--?将非可视元素(例如服务、值对象)放在此处?-->??
  52. ????</fx:Declarations>??
  53. ????<s:Button?x="156"?y="56"?label="按钮"?click="button1_clickHandler(event)"/>??
  54. ????<s:TextInput?x="20"?y="56"?id="txt_socket"/>??
  55. ????<s:Label?x="20"?y="104"?id="l_status"/>??
  56. ????<s:Label?x="234"?y="65"?id="l_result"/>??
  57. </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/> “另一方面监听返回的安全策略。安全策略接收成功后, FlashPlayer 就断开验证的 Socket ,然后再运行程序本身的 Socket 。在整个 SWF 运行期间,无论你请求多少次,只要域相同, FlashPlayer 就只验证一次。这里有两个重点:
?
第一个是验证的 Socket 和程序的 Socket 是两个 Socket 。所以你在本地测试时,服务端监听到 N 个 Socket 请求,但布置到服务端后,服务端会监听到 N+1 个请求。
第二是验证的 Socket 发送“ <policy-file-request/> “请求和接收你的策略文件是没有先后关系的,所以你没必要接收完“ <policy-file-request/> “后才发策略文件。我的做法是只要监听到请求,就把策略字符串发过去。
-----------------------------------------------------------------------------------
?
那么简单的说,如果Flex项目依赖其它语言的服务器的话(比如依赖J2EE服务器),在flex的socket客户端向JavaSocket服务器发送请求之前,Flex会优先发送一个安全验证消息,如果java服务器不返回验证消息则当前socket通信失败。
解决办法有很多种,我在网上也看了很多,但是很多写得有问题。
根据我多方调查,个人觉得这种方案比较靠谱:
在Java服务器端创建一个端口号为843的ServerSocket监听Flex安全沙箱验证消息,如果接收到<policy-file-request/>文件信息,则向客户端返回XMl验证内容:“<?xml version="1.0"?><cross-domain-policy><site-control permitted-cross-domain-policies="all"/><allow-access-from domain="*" to-ports="*"/></cross-domain-policy>”
具体代码如下:
Java代码??
  1. /**??
  2. ?*?处理与Flex认证的线程类??
  3. ?*?@author?Administrator??
  4. ?*/??
  5. public?class?PolicyThread?implements?Runnable?{ ??
  6. ????private?final?String?policy_xml?=?"<policy-file-request/>"; ??
  7. ????private?final?String?cross_xml?=?"<?xml?version="1.0"?><cross-domain-policy><site-control?permitted-cross-domain-policies="all"/><allow-access-from?domain="*"?to-ports="*"/></cross-domain-policy>"; ??
  8. ????private?Socket?socket; ??
  9. ???? ??
  10. ????public?PolicyThread(Socket?socket){ ??
  11. ????????this.socket?=?socket; ??
  12. ????} ??
  13. ???? ??
  14. ????@Override??
  15. ????public?void?run()?{ ??
  16. ????????try?{ ??
  17. ????????????//接收并发送Flex安全验证请求???
  18. ????????????BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(socket.getInputStream())); ??
  19. ????????????PrintWriter?pw?=?new?PrintWriter(socket.getOutputStream()); ??
  20. ????????????char[]?by?=?new?char[22]; ??
  21. ????????????br.read(by,?0,?22); ??
  22. ????????????String?s?=?new?String(by); ??
  23. ????????????if(s.equals(policy_xml)){ ??
  24. ????????????????System.out.println("接收policy-file-request认证"); ??
  25. ????????????????pw.print(cross_xml); ??
  26. ????????????????pw.flush(); ??
  27. ????????????????br.close(); ??
  28. ????????????????pw.close(); ??
  29. ????????????????socket.close(); ??
  30. ????????????????System.out.println("完成policy-file-request认证"); ??
  31. ????????????} ??
  32. ????????}?catch?(IOException?e)?{ ??
  33. ????????????if(!socket.isClosed()){ ??
  34. ????????????????try?{ ??
  35. ????????????????????socket.close(); ??
  36. ????????????????}?catch?(IOException?e1)?{ ??
  37. ????????????????????e1.printStackTrace(); ??
  38. ????????????????} ??
  39. ????????????} ??
  40. ????????????throw?new?RuntimeException("执行policy认证时发生异常",e); ??
  41. ????????} ??
  42. ????} ??
  43. ??
  44. }??
Java代码??
  1. public?class?PolicyServer?implements?Runnable{ ??
  2. ???? ??
  3. ????private?final?int?policy_port?=?843; ??
  4. ????private?boolean?status?=?true; ??
  5. ???? ??
  6. ????private?ServerSocket?server?=?null; ??
  7. ????@Override??
  8. ????public?void?run()?{ ??
  9. ????????//创建安全验证服务器???
  10. ????????server?=?SocketUtil.getServerSocket(policy_port); ??
  11. ???????? ??
  12. ????????while(status){ ??
  13. ????????????Socket?socket?=?SocketUtil.getSocket(server); ??
  14. ????????????new?Thread(new?PolicyThread(socket)).start(); ??
  15. ????????} ??
  16. ????} ??
  17. ???? ??
  18. ???? ??
  19. ????/**??
  20. ?????*?启动服务器??
  21. ?????*/??
  22. ????public?void?startPolicy(){ ??
  23. ????????new?Thread(this).start(); ??
  24. ????} ??
  25. ???? ??
  26. ????/**??
  27. ?????*?关闭服务器??
  28. ?????*/??
  29. ????public?void?stopPolicy(){ ??
  30. ????????status?=?false; ??
  31. ????????if(server!=null?&&?!server.isClosed()){ ??
  32. ????????????try?{ ??
  33. ????????????????server.close(); ??
  34. ????????????}?catch?(IOException?e)?{ ??
  35. ????????????????e.printStackTrace(); ??
  36. ????????????} ??
  37. ????????} ??
  38. ????} ??
  39. }??
?
Flex客户端向Java发送第一次Socket请求(例子里的端口号是10086)时,ServerSocket843端口会收到安全沙箱验证,随后server将正确的验证消息返回给Flex客户端,Flex认证成功后真正的10086端口Socket连结就已经搭建了,随后双方就可以畅通无阻通信了(一次会话只进行一次沙箱验证)。
?
?
  • Servlet启动ServerSocket
我通常比较喜欢创建一个servlet,在web.xml中配置容器启动时运行servlet的init方法,这样端口号为10086和843的serverSocket就会启动:
Java代码??
  1. public?class?InitServers?extends?HttpServlet?{ ??
  2. ????private?static?final?long?serialVersionUID?=?1L; ??
  3. ??????? ??
  4. ????/**??
  5. ?????*?@see?HttpServlet#HttpServlet()??
  6. ?????*/??
  7. ????public?InitServers()?{ ??
  8. ????????super(); ??
  9. ????} ??
  10. ??
  11. ????/**??
  12. ?????*?@see?Servlet#init(ServletConfig)??
  13. ?????*/??
  14. ????public?void?init(ServletConfig?config)?throws?ServletException?{ ??
  15. ????????new?PolicyServer().startPolicy(); ??
  16. ????????new?SocketServer().startSocket(); ??
  17. ????} ??
  18. ??
  19. ????/**??
  20. ?????*?@see?HttpServlet#doGet(HttpServletRequest?request,?HttpServletResponse?response)??
  21. ?????*/??
  22. ????protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{ ??
  23. ????????//?TODO?Auto-generated?method?stub???
  24. ????} ??
  25. ??
  26. ????/**??
  27. ?????*?@see?HttpServlet#doPost(HttpServletRequest?request,?HttpServletResponse?response)??
  28. ?????*/??
  29. ????protected?void?doPost(HttpServletRequest?request,?IOException?{ ??
  30. ????????//?TODO?Auto-generated?method?stub???
  31. ????} ??
  32. ??
  33. }??
?web.xml
?
Xml代码??
  1. <servlet>??
  2. ????????<display-name>InitServers</display-name>??
  3. ????????<servlet-name>InitServers</servlet-name>??
  4. ????????<servlet-class>socket.InitServers</servlet-class>??
  5. ????????<load-on-startup>1</load-on-startup>??
  6. ????</servlet>??
?
以上一个完整的Flex+Java的Socket通信就完成了。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读