- 浏览: 18695 次
最新评论
Flex socket通信实践学习笔记(2)-1
2011年04月17日
前面,阿堂和朋友们简单聊了一下,给出了一些FLEX和JAVA交互的操作图的界面一文(见 Flex socket通信实践学习笔记(1)),见阿堂的新浪空间(http://blog.sina.com.cn/s/blog_4c925dca0100s38p.ht ml),由于阿堂平常一直比较忙,所以代码没有粘出来,今天我就给出该操作图相应的后台服务端java代码和客户端的FLEX代码.对于flex和JAVA的交互,我这里也简单总结一下,谈一下自己的看法!
1.flex和java交互时,需要三次握手过程,握手成功后,flex客户端会检测通信端口中是否存在安全策略文件,此时客户端发送以下报文内容.
服务端在收到该报文后,应该向客户端发送安全策略文件。
//Flex 安全策略文件
String xml ="";
xml = xml+"";
xml = xml+"";
xml = xml+"";
之后再进行正常Socket通信.
所以,朋友们会在阿堂后面粘出来的代码中看到有如下代码
if(head.equals("")){
pw.print(xml+"\0");
pw.flush();
}else{
...
}
代码的判断,对于安全策略文件,不是阿堂这篇文章讨论的重点,所以我就不再详细说明了。有兴趣的朋友可以继续看flex安全策略文件方面的介绍和说明,网上有很多这方面的介绍
2.flex和java交互中需要约定socket方面的通信协议或者说是rule.注意,这个是相对于开发的项目或游戏本身约定的通信协议,也就是说对于开发某个游戏,双方需要实际交互过程中,来议定的一些规则.如下面简单的网络聊天室,就议定了五类规则,0表示登录信息,1表示普通信息,2表示客户端总人数,3表示离开信息,4表示用户列表信息. (当然,我们用BlazeDS,apache mina等框架开发较为大中型的flash游戏时,我们议定的规则会比下述规则复杂得多.象我们部门其它项目组,开发的“德州扑克”,用的apache mina和flex交互时,就议定了2m-30种协议规则,每种规则传递的不是简单的数字,而是更为丰富的Array数组。java端是传递的JSon格式到flex客户端,flex端传递给java端是Array数组)但是,不管传递的数据有多复杂或者用什么框架,如BlazeDS,apache mina,FMS,Red5等,Flex和Java交互的基本原理都是一样的,只不过,用这些框架时,我们对于Socket的框架少了一些操作而也,很多的对于Socket框架方面的底层封装少了很多的操作,大大方便了Flex和服务端的交互.
(1)java后台服务端
//用户登录消息头
public static final String LOGIN_HEAD = "0";
//发送普通消息头
public static final String MESSAGE_HEAD = "1";
//客户端人数消息头
public static final String CLIENT_NUM_HEAD = "2";
//客户端离开消息头
public static final String LOGIN_OUT_HEAD = "3";
//用户列表消息头
public static final String USER_LIST = "4";
(2)flex客户端
// 用户登录消息头
public static const LOGIN_HEAD:String = "0";
// 发送普通消息头
public static const MESSAGE_HEAD:String = "1";
// 客户端人数消息头
public static const CLIENT_NUM_HEAD:String = "2";
// 客户端离开消息头
public static const LOGIN_OUT_HEAD:String= "3";
//如果是用户列表消息头
public static const USER_LIST:String = "4";
(3)Java服务端,主要用了三个类:一个主程序启动类启动监听服务MainServer.java,Socket线程处理类处理与每一个客户端的通信
SocketThread.java,广播类BroadCaster.java广我们的消息给所有的客户端。这实际上比较典型的设计模式--观察者设计模式。
(4)Flex客户端 logWin.mxml,SocketExample.mxml
服务端代码如下
代码如下
package com.chat.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress; public class MainServer { //监听端口
private static final int SERVER_PORT = 9999;
//服务器
private ServerSocket server;
//广播者
private BroadCaster broadCaster = new BroadCaster();
public MainServer(){
}
public void startServer(){
//Flex 安全策略文件
String xml ="";
xml = xml+"";
xml = xml+"";
xml = xml+"";
try{
//创建server端口 9999
server = new ServerSocket(SERVER_PORT);
System.out.println("---服务端启动成功 ! 监听端口:"+SERVER_PORT);
System.out.println("---等待客户端连接");
while(true){
//获得客户端连接socket
Socket socket = server.accept();
System.out.println("----客户端已连接:"+socket.getRemoteSocketAddress());
//Flash socket跨域访问设置
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-
8"));
PrintWriter pw = new PrintWriter(socket.getOutputStream());
//接收用户名
char[] by = new char[22];
br.read(by,0,22);
String head = new String(by);
if(head.equals("")){
pw.print(xml+"\0");
pw.flush();
}else{
//截取第一个字符串,判断消息类型
String cmd = head.substring(0, 1);
if(BroadCaster.LOGIN_HEAD.equals(cmd)){
//如果接收的是登录信息
String userName = head.substring(1, head.indexOf('\n'));
System.out.println(userName+" 上线了! ");
//将socket添加到广播对象 Vector中
broadCaster.add(socket);
//创建Scoket线程与客户端通信
SocketThread thread = new SocketThread(broadCaster,socket,userName);
//启动线程
thread.start();
//发送在线人数信息到客户端
broadCaster.sendClientNumToAll();
//发送登录信息给所有客户端
broadCaster.sendLoginInfoToAll(userName);
//将用户名添加到用户列表中
broadCaster.addUserName(userName);
//发送所有用户名列表,给所有客户端
broadCaster.sendUserListToAll(); } } } }catch(IOException e){ e.printStackTrace(); } } public static void main(String[] args){ //启动Socket服务器
MainServer mainServer = new MainServer();
mainServer.startServer();
}
}
package com.chat.demo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class SocketThread extends Thread {
//保存广播引用
private BroadCaster broadCaster;
//用户名
private String userName;
//保存套接字引用
private Socket socket;
//套接字输入流
private BufferedReader br;
public SocketThread(BroadCaster broadCaster,Socket socket,String userName){
this.broadCaster = broadCaster;
this.socket = socket;
this.userName = userName;
}
public void run(){
try{
if(socket !=null && !socket.isClosed()){
//获取客户端发送过来的信息
br = new BufferedReader(new InputStreamReader(this.socket.getInputStream(),"UT F-8"));
//消息原始内容
String msg = null;
//消息头
String head = null;
//消息主体
String msgBody = null;
//发送的消息内容
String sendMsg = null;
while((msg = br.readLine()) != null){
head = msg.substring(0, 1);
msgBody = msg.substring(1);
if(BroadCaster.LOGIN_HEAD.equals(head)){
//如果是登录信息
sendMsg = msgBody+"登录了";
System.out.println(sendMsg);
//发送在线人数信息到客户端
broadCaster.sendClientNumToAll();
//用户登录消息,则发送用户登录消息到所有客户端
broadCaster.sendLoginInfoToAll(msgBody);
//发送所有用户列表给所有客户端
broadCaster.addUserName(msgBody);
//发送用户信息列表给所有客户端
broadCaster.sendUserListToAll();
}else if(BroadCaster.MESSAGE_HEAD.equals(head)){
System.out.println(msgBody);
//如果接收的是普通信息,则发送该消息到所有的客户端
broadCaster.sendMessageToAll(msgBody); } } } else{ System.out.println("---------连接已经关闭--------------");
}
}catch(Exception e){
}finally{
try{
//客户端离开了,移除广播者对象中的Socket
broadCaster.remove(socket);
//关闭输入流
if(br != null){
br.close();
}
//关闭Socket连接,释放资源
if(socket != null){
socket.close();
}
br = null;
socket = null;
System.out.println("客户端离开");
//发送当前在线人数消息给所有的客户端
broadCaster.sendClientNumToAll();
//移出用户登录名称
broadCaster.removeUserName(userName);
//发送用户离开消息给每一个客户端
broadCaster.sendLoginOutInfoToAll(userName);
//发送在线用户信息列表消息给所有客户端
broadCaster.sendUserListToAll();
}catch(IOException e){
}
}
}
}
package com.chat.demo;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Vector;
public class BroadCaster {
//用户登录消息头
public static final String LOGIN_HEAD = "0";
//发送普通消息头
public static final String MESSAGE_HEAD = "1";
//客户端人数消息头
public static final String CLIENT_NUM_HEAD = "2";
//客户端离开消息头
public static final String LOGIN_OUT_HEAD = "3";
//用户列表消息头
public static final String USER_LIST = "4";
//Socket 客户端连接用户名
private Vector userNameVector = new Vector();
//Scoket 客户端连接Vector
private Vector socketVector = new Vector();
public Vector getSocketVector() {
return socketVector;
}
public void setSocketVector(Vector socketVector) {
this.socketVector = socketVector; } //添加用户名
public void addUserName(String userName){
this.userNameVector.add(userName);
}
//删除用户名
public void removeUserName(String userName){
this.userNameVector.remove(userName);
}
//添加socket
public void add(Socket socket){
this.socketVector.add(socket);
}
//移除socket
public void remove(Socket socket){
this.socketVector.remove(socket);
}
//发消息给所有客户端
private void send(String head,String message){
PrintWriter pw = null; //输出流
Socket sock;
if(this.socketVector != null){
for(int i=0;i0){
StringBuffer sb = new StringBuffer();
//循环用户名列表生成消息
for(int i = 0;iFlex客户端中接收消息按此分隔获取用户名
sb.append("-");
}
if(sb.length()>0){
//去掉最后一个'-'分隔符号
sb.deleteCharAt(sb.length()-1);
}
//发送给所有客户端
this.send(USER_LIST, sb.toString());
}
}
}
[b][/b]
发表评论
-
(转载)C++中枚举与字符串相互转换
2012-07-06 09:52 4133有的时候我们喜欢使用一些外部的文件保存管理一些配置信息,这 ... -
awk教程
2012-07-06 09:45 602一个年轻的程序员问一个老程序员(一个比较牛逼的公司的CTO ... -
正则表达式中附加参数的用法
2012-07-06 09:38 611附件参数g的用法: 1)对于表达式对象的exec方法, ... -
asp.net gridview美化
2012-07-06 09:30 1270i am now in university(HIT@We ... -
javascript js 删除表格的行、单元列
2012-07-05 20:45 645大发现,大家在贴代码的时候。系统会自动加上一些代码或注释之 ... -
具有可过滤功能的JList组件【Swing】
2012-07-03 13:44 774【场景】:在一个列表中,可以通过输入某个字符,而动态过滤列 ... -
Flex应用程序背景颜色渐变
2012-07-02 12:29 616今天突然看见CSDN一个美女高手写的小东西,发现Flex背 ... -
Flex操作Json数据示例
2012-07-02 12:29 674Flex操作Json数据示例 本示例中需要用到JSO ... -
FLEX4中 获取JSON数据的一个例子
2012-07-02 12:29 788公司要求使用JSON格式来获取服务器端的数据 通过 ... -
Flex获取操作XML示例
2012-07-02 12:28 531/****** ".",&qu ... -
Flex 4 Canvas backgroundImage 问题
2012-07-02 12:28 739倾听,慎言,勇行,自省... ... -
GNU Make 中文手册v3.8 学习 ( 3/3 )
2012-07-01 10:05 1018GNU Make 中文手册v3.8 学习 ( 3/3 ) ... -
Web前端开发之“常见模块你真的很了解吗?”
2012-07-01 10:05 743标题和内容模 ... -
Lex和yacc工具介绍
2012-07-01 10:05 914在编译过程中,词 ... -
谈谈我对未来的想法吧
2012-07-01 10:05 680来总行珠海研发中 ... -
终于搞清楚了Flex到底是收费还是免费
2012-06-30 16:30 1613终于搞清楚了Flex到底是收费还是免费 2010年06月29 ... -
结合实际项目谈谈Extjs、Flex、Jquery等富因特网时代框架的用武之处
2012-06-30 16:30 668结合实际项目谈谈Extjs ... -
全面认识Flex安全沙箱
2012-06-30 16:30 602全面认识Flex安全沙箱 2 ... -
为Flex应用添加实时组件
2012-06-30 16:30 456为Flex应用添加实时组件 2011年06月30日 在很 ...
相关推荐
flex3读书笔记----flex整合hibernate
Flex builder 学习学习 2007-10-08Flex builder 学习学习 2007-10-08Flex builder 学习学习 2007-10-08
Flex 的socket通信 提供实例代码
Flex学习笔记Flex学习笔记Flex学习笔记Flex学习笔记Flex学习笔记
这是flex,快速的词法分析器生成器。 flex是用于生成扫描仪的工具:识别文本中的词汇模式的程序。 直接打开压缩包就是原文件 flex代码库保存在GitHub上的Git中。 可以在github版本页面上找到带有某些中间文件的...
1 2 跟我StepByStep学FLEX教程------Flex3及Flex Builder安装(原创) 1 3 跟我StepByStep学FLEX教程------Hello World(原创) 1 4 跟我StepByStep学FLEX教程------可视化页面组件(原创) 1 5 跟我StepByStep学...
非常好DEMO参考,这个项目已经转到Apache名下了,最新的版本1.2,308个例子,已经全站打包,搜索:flex-tour-de-flex-component-explorer-1.2-308demo。开源代码http://flex.apache.org/download-tourdeflex.html
1.背景:Flex Socket通信及安全策略,使用flex实现客户端,java实现服务端; 2.重点解决安全策略问题:将flash发布为html格式后,本地访问页面后,一般可以与服务器进行socket通信;但是部署到tomcat服务器上后无法...
Flex 全景图源码-----街景 Flex 全景图源码-----街景
spring-flex-1.5.0.M2-dist.zip spring-flex-1.5.0.M2 spring-flex-1.5.0.M2.jar SBI
非常好DEMO参考,这个项目已经转到Apache名下了,最新的版本1.2,308个例子,已经全站打包,搜索:flex-tour-de-flex-component-explorer-1.2-308demo。开源代码http://flex.apache.org/download-tourdeflex.html
flex 和java 之间的相互通信
最近开始学习Flex,其中用到了AS,AS2到AS3发生了很大的变化,完全的面向对象,知道这个特点以后我也一直没有特意的好好去学学AS3,但是随着最近学习的深入,还是有必要学习一下
blaseDS框架实现Flex与J2EE的通信Demo ----------------------------------- 学习笔记-------flex后台通信-------- -----------------------------------
跟我StepByStep学FLEX教程------王一松
跟我StepByStep学FLEX教程------王一松.pdf
研究flex的通信问题,写了一个flex的Socket与C#通信例子,类似QQ软件的客户端和服务器端。
安装了Flex插件的Eclipse项目工程 博文链接:https://lib.iteye.com/blog/202883
本章实例源码 博文链接:https://lib.iteye.com/blog/209792