使用Flash的XMLSocket与Servlet建立长连接(2,建立JavaScript类)

来源:互联网 发布:淘宝优惠论坛 编辑:程序博客网 时间:2024/04/27 14:50

使用Flash的XMLSocket与Servlet建立长连接(2,建立JavaScript类)

为了更好的使用前面的flash控件,我们还需要建立一个易于使用的JavaScript类

Servlet是运行于jsp/servlet容器中的,它本身是基于http协议的
而socket连接是基于TCP/IP协议的,http协议运行于TCP/IP协议之上
所以我们直接通过socket连接到servlet是不行的
这就好比两个不同国家的人说话,a 对 c说话必须通过b来翻译
所以我们需要对socket向servlet发送的请求转换成http协议来发送请求
下面是JavaScript的实现:

将下面的文件分别保存

/*
 * 基础类定义
 * $RCSfile: com.inet.base.js,v $
 * $Revision: 1.1  $
 *
 * Copyright (C) 2005 inet, Inc. All rights reserved.
 *
 * This software is the proprietary information of inet, Inc.
 * Use is subject to license terms.
 *
 * @author: chenyankui
 * @Date:   2006-10-11
 */
var com = {};

com.inet = {};

com.inet.inet = {};

 

/*
 * 对http协议的封装, 在Tomcat5.028和WebSphere5.1下测试通过
 *
 * $RCSfile: com.inet.http.js,v $
 * $Revision: 1.1  $
 *
 * Copyright (C) 2005 inet, Inc. All rights reserved.
 *
 * This software is the proprietary information of inet, Inc.
 * Use is subject to license terms.
 *
 * @author: chenyankui
 * @Date:   2006-10-11
 */

com.inet.http.Page = {
 
 getContextPath : function()
 {
  if(window.location.protocol.toLowerCase() == "http:")
  {
   var pathname = window.location.pathname;

   var k = pathname.indexOf("/", 1);

   if(k < 0)
   {
    return ".";
   }
   else
   {
    // 有时返回的contextpath没有前缀"/" 所以此出添加一个 "/"
    return  "/" + pathname.substring(0, k).replace("/", "");
   }
  }
  else
  {
   return ".";
  }
 },

 getParameter : function(paramName)
 {
  return this.getQueryValue(window.document.location.search, paramName);
 },

 getQueryValue: function (sorStr, panStr)
 {
  var vStr = "";
  
  if(sorStr == null || sorStr == "" || panStr == null || panStr == "") return vStr;

  sorStr = sorStr.toLowerCase();

  panStr += "=";
  
  var itmp = sorStr.indexOf(panStr);

  if(itmp < 0){return vStr;}
  
  sorStr = sorStr.substr(itmp + panStr.length);
  
  itmp=sorStr.indexOf("&");

  if(itmp < 0)
  {
   return sorStr;
  }
  else
  {
   sorStr = sorStr.substr(0, itmp);
   return sorStr;
  }
 }
};

com.inet.http.HttpRequestHead = function()

 var _line = "/r/n";
 
 var _method = {
  "GET"     : "GET",
  "PUT"     : "PUT",
  "POST"    : "POST",
  "HEAD"    : "HEAD",
  "TRACE"   : "TRACE"
  "DELETE"  : "DELETE",
  "OPTIONS" : "OPTIONS",
 };

 var _protocol = {"HTTP1" : "HTTP/1.0", "HTTP1_1" : "HTTP/1.1"};

 var _head = new Array();

 this.url  = null;

 this.host = null;
 this.port = null;

 this.data = null;

 this.method = "GET";

 this.addHeader = function(name, value)
 {
  _head.push(name + ": " + value)
 };

 this.getRequestHead  = function()
 {
  if(this.method == null)
  {
   this.method = "GET";
  }
  else
  {
   this.method = this.method.toUpperCase();
  }
  
  if(_method[this.method] == null)
  {
   this.method = "GET";
  }
  
  var str = this.method + " " + this.url + " HTTP/1.1" + _line;
  
  str += "Accept: */*" + _line;
  str += "Accept-Language: " + window.navigator.userLanguage + _line;
  str += "Accept-Encoding: gzip, deflate" + _line;

  for(var i = 0; i < _head.length; i++)
  {
   str += _head[i] + _line;
  }
  
  if(this.method == "POST")
  {
   str += "Content-Type: application/x-www-form-urlencoded" + _line;
  }

  if(this.method == "POST" && this.data != null && this.data.length != null)
  {
   str += "Content-Length: " + this.data.length + _line;
  }
  
  str += "User-Agent: " + window.navigator.userAgent + _line;
  str += "Host: " + this.host + ":" + this.port + _line;
  
  str += "Cache-Control: no-cache" + _line;
  str += "Connection: Keep-Alive"  + _line;

  var cookie = window.document.cookie;

  cookie = "author=" + escape("chenyankui") + "; " + cookie;

  if(cookie != null && cookie != "")
  {
   str += "Cookie: " + window.document.cookie + _line;
  }

  str += _line;
  
  // 附加数据
  if(this.method == "POST" && this.data != null)
  {
   str += this.data;
  }

  return str;
 };
};

/*
 * socket的封装类
 * 其中request函数直接封装了对servlet的请求
 * 有一部分注释是关于Flash的API的注释, 可以参看这些注释得到更过的关于当前客户机的flash版本的信息
 * $RCSfile: com.inet.inet.js,v $
 * $Revision: 1.1  $
 *
 * Copyright (C) 2005 inet, Inc. All rights reserved.
 *
 * This software is the proprietary information of inet, Inc.
 * Use is subject to license terms.
 *
 * @author: chenyankui
 * @Date:   2006-09-28
 */

var CRLF = "/r/n";

com.inet.inet.Socket = function()
{
 this.sid = window.document.Socket.createSocket();

 this.host = null;
 this.port = null;

 this.onXml     = null;
 this.onData    = null;
 this.onClose   = null;
 this.onConnect = null;

 this.connect = function(_host, _port)
 {
  this.host = _host;
  this.port = _port;

  window.document.Socket.connect(this.sid, _host, _port);
 };

 this.close = function()
 {
  window.document.Socket.closeSocket(this.sid);
 };

 this.send  = function(src)
 {
  window.document.Socket.sendString(this.sid, src + CRLF);
 };

 this.request = function(url, method, data)
 {
  if(arguments.length < 3)
  {
   throw {name: "InvalidArgumentsException", message: "arguments.length != 3"};
  }

  if(url == null)
  {
   throw {name: "NullPointerException", message: "URL IS NULL !"};
  }
  
  var http = new com.inet.http.HttpRequestHead();

  http.url  = url
  http.host = this.host;
  http.port = this.port;
  http.data = data;
  http.method = method;

  var version = com.inet.inet.Socket.getFlashVersion();

  if(version != null && version.length > 4)
  {
   version = version.substring(4);

   http.addHeader("x-flash-version", version);
  }

  head = http.getRequestHead();

  try
  {
   window.document.Socket.sendString(this.sid, head);
  }
  catch(e)
  {
   alert(e.name + ":" + e.message);
  }
 };

 com.inet.inet.Socket.map[this.sid] = this;
 
 window.document.Socket.addSocketEvent(this.sid);
}

com.inet.inet.Socket.map = {};

com.inet.inet.Socket.create = function(_dom)
{
 if(_dom == null)
 {
  _dom = window.document;
 }
 
 var _fls = _dom.getElementById("Socket");
 
 // 如果Socket对象已经被创建
 if(_fls != null && typeof(_fls) == "object" && _fls.classid == "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000")
 {
  alert("Socket is created !");
  return;
 }
  
 _fls = _dom.createElement("object");
 
 _dom.appendChild(_fls);

 _fls.id       = "Socket";
 _fls.width    = "500";
 _fls.height   = "200";
 _fls.classid  = "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
 _fls.codeBase = "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0";
 
 var _param = null;
 var _names = ["movie",         "quality", "bgcolor"];
 var _valus = ["./fls/net.swf", "high",    "#C0C0C0"];
 
 for(var _i = 0; _i < _names.length; _i++)
 {
  _param = _dom.createElement("param");

  _param.name  = _names[_i];
  _param.value = _valus[_i];

  _fls.appendChild(_param);
 }
}

com.inet.inet.Socket.setLogLevel = function(level)
{
 window.document.Socket.setLogLevel(level);
}

com.inet.inet.Socket.loadPolicyFile = function(uri)
{
 window.document.Socket.loadPolicyFile(uri);
}

/*
avHardwareDisable
布尔值,指定对用户的摄像头和麦克风的访问是已经通过管理方式禁止 (true) 还是允许 (false)。

hasAccessibility
布尔值,如果播放器正在支持 Flash Player 与辅助功能之间进行通讯的环境中运行,则为 true;否则为 false。

hasAudio
指定系统是否有音频功能。

hasAudioEncoder
指定 Flash Player 是否可对音频流进行编码。

hasEmbeddedVideo
布尔值,如果播放器正在支持嵌入视频的系统上运行,则为 true;否则为 false。

hasIME
指示系统是否安装了输入法编辑器 (IME)。

hasMP3
指定系统是否有 MP3 解码器。

hasPrinting
布尔值,如果播放器正在支持打印的系统上运行,则为 true;否则为 false。

hasScreenBroadcast
布尔值,如果播放器支持开发通过 Flash Communication Server 运行的屏幕广播应用程序,则为 true;否则为 false。

hasScreenPlayback
布尔值,如果播放器支持正在播放通过 Flash Communication Server 运行的屏幕广播应用程序,则为 true;否则为 false。

hasStreamingAudio
布尔值,如果播放器可以播放音频流,则为 true;否则为 false。

hasStreamingVideo
布尔值,如果播放器可以播放视频流,则为 true;否则为 false。

hasVideoEncoder
指定 Flash Player 是否可对视频流进行编码。

isDebugger
布尔值,指示播放器是正式发布的版本 (false),还是特殊的调试版本 (true)。

language:String [只读]
指示运行播放器的系统的语言。

localFileReadDisable
布尔值,指示对用户硬盘的读取权限是已经通过管理方式禁止 (true) 还是允许 (false)。

manufacturer:String [只读]
字符串,指示 Flash Player 制造商,其格式为"Macromedia OSName"(其中 OSName 可以为 "Windows"、"Macintosh"、"Linux" 或"Other OS Name")。

os:String [只读]
字符串,指示当前的操作系统。

pixelAspectRatio:Number [只读]
整数,指示屏幕的像素高宽比。

playerType:String [只读]
字符串,指示播放器的类型。

screenColor:String [只读]
字符串,指示屏幕的颜色。

screenDPI:Number [只读]
数字,指示屏幕的每英寸点数 (dpi) 分辨率,以像素为单位。

screenResolutionX:Number [只读]
整数,指示屏幕的最大水平分辨率。

screenResolutionY:Number [只读]
整数,指示屏幕的最大垂直分辨率。

serverString:String [只读]
URL 编码的字符串,用于指定每个 System.capabilities 属性的值。

version:String [只读]
字符串,包含 Flash Player 平台和版本信息(例如 "WIN 8,0,0,0")。

var flashVersion = com.inet.inet.Socket.getSystemProperty("version");

实现原理: System.capabilities拥有以上的静态方法
此处使用关联数组的方法调用这些方法
*/
com.inet.inet.Socket.getSystemProperty = function(key)
{
 return window.document.Socket.getSystemProperty(key);
};

com.inet.inet.Socket.getFlashVersion = function()
{
 return window.document.Socket.getSystemProperty("version");
};

function _getRequestHead(url, method, data, host, port)
{
 var line = "/r/n";

 if(arguments.length < 3)
 {
  throw {name: "InvalidArgumentsException", message: "arguments.length != 3"};
 }

 if(url == null)
 {
  throw {name: "NullPointerException", message: "URL IS NULL !"};
 }

 var m = null;

 if(method == null)
 {
  m = "GET";
 }
 else
 {
  m = method.toUpperCase();
 }
 
 var ms = {GET: true, POST: true, HEAD: true, DELETE: true, OPTIONS: true, PUT: true, TRACE: true};

 if(ms[m] == null)
 {
  m = "GET";
 }
 
 var head = m + " " + url + " HTTP/1.1" + CRLF;

 head += "Accept: */*" + line;
 head += "Accept-Language: " + window.navigator.userLanguage + line;
 head += "Accept-Encoding: gzip, deflate" + line;
 
 if(m == "POST")
 {
  head += "Content-Type: application/x-www-form-urlencoded" + line;
 }

 if(m == "POST" && data != null && data.length != null)
 {
  head += "Content-Length: " + data.length + line;
 }

 head += "User-Agent: " + window.navigator.userAgent + line;
 head += "Host: " + host + ":" + port + line;
 
 head += "Cache-Control: no-cache" + line;
 head += "Connection: Keep-Alive"  + line;

 var cookie = window.document.cookie;

 cookie = "author=" + escape("chenyankui") + "; " + cookie;

 if(cookie != null && cookie != "")
 {
  head += "Cookie: " + window.document.cookie + line;
 }

 head += line;
 
 // 附加数据
 if(m == "POST" && data != null)
 {
  head += data;
 }

 return head;
}
 

 


/*
 * 封装事件
 * 当有事件发生时,flash调用这些函数, 这些函数再把相应的事件转发到对应的JavaScript的Socket对象事件中处理
 * $RCSfile: com.inet.evnt.js,v $
 * $Revision: 1.1  $
 *
 * Copyright (C) 2005 inet, Inc. All rights reserved.
 *
 * This software is the proprietary information of inet, Inc.
 * Use is subject to license terms.
 *
 * @author: chenyankui
 * @Date:   2006-09-28
 */
function $SocketOnXml(sid, src)
{
 // logger.debug("$SocketOnXml 被调用 " + sid);

 var html= __$filter(src);

 var obj = com.inet.inet.Socket.map[sid];

 if(obj != null && obj.onXml != null && (typeof(obj.onXml)).toLowerCase() == "function")
 {
  obj.onXml(http);
 }
}

/**
 * 该函数将被Flash调用
 * Flash8存在一个Bug, 当Flash调用JavaScript函数的时候, 如果参数是字符串类型, 并且参数中包含有特殊字符
 * 将发生错误, 这应该是Flash8的一个Bug, 解决办法是对字符串参数进行编码, 然后再传递过来
 * Flash8的escape(x:String)函数对字符串的编码不同于JavaScript的escape(x)函数
 * Flash8的escape(x:String)函数将字符串编码成URL编码, 所以此处需要对字符串进行URL解码
 **/
function $SocketOnData(sid, src)
{
 // logger.debug("$SocketOnData 被调用 " + sid);

 var html= __$filter(src);
 
 var obj = com.inet.inet.Socket.map[sid];

 if(obj != null && obj.onData != null && (typeof(obj.onData)).toLowerCase() == "function")
 {
  obj.onData(html);
 }
}

function $SocketOnClose(sid)
{
 //logger.debug("$SocketOnClose 被调用 " + sid);

 var obj = com.inet.inet.Socket.map[sid];

 if(obj != null && obj.onClose != null && (typeof(obj.onClose)).toLowerCase() == "function")
 {
  obj.onClose();
 }
}

function $SocketOnConnect(sid, success)
{
 //logger.debug("$SocketOnConnect 被调用: " + sid);

 var obj = com.inet.inet.Socket.map[sid];

 if(obj != null && obj.onConnect != null && (typeof(obj.onConnect)).toLowerCase() == "function")
 {
  obj.onConnect(success);
 }
}

function __$filter(src)
{
 var html = window.decodeURI(src);
 
 // head必须和servlet中定义的一致
 var head = "<![CDATA[HTTP-HEAD-END]]>";
 
 // 过滤掉http头
 // 该过滤依赖于服务端servlet, 服务器端的servlet在发送数据之前必须先发送[HTTP-HEAD-END]这里的过滤才能生效
 var k = html.indexOf(head);
 
 if(k > -1)
 {
  return html.substring(k + head.length);
 }

 return html;
}

到此为止,JavaScript已经和Flash建立了联系。以后我们将不再调用flash的net.swf
而是直接调用JavaScript来完成工作

下面一步,我们将建立Java端的处理程序

 

原创粉丝点击