﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-流浪妖精のSKY-文章分类-特色技术</title><link>http://www.cnitblog.com/flutist1225/category/3822.html</link><description>&lt;div align="right"&gt;&lt;iframe src="http://weather.265.com/weather.htm" width="168" height="54" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;!--- daliy English --&gt;
&lt;span id="dict_daily"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;script language="JavaScript" src="http://dict.cn/daily.php" defer="defer"&gt;&lt;br /&gt;
&lt;/script&gt;
&lt;!--Music --&gt;
&lt;span style="display:none"&gt;
&lt;embed src="http://www.c188.com/all/1111wmatt98/new3/new2/1368/6.wma" loop=true autostart=true volume=100 type=audio/x-pn-realaudio-plugin Initfn=load-types mime-types=mime.types &gt;
&lt;/span&gt;</description><language>zh-cn</language><lastBuildDate>Thu, 29 Sep 2011 05:00:13 GMT</lastBuildDate><pubDate>Thu, 29 Sep 2011 05:00:13 GMT</pubDate><ttl>60</ttl><item><title>用推送技术动态更新页面内容 </title><link>http://www.cnitblog.com/flutist1225/articles/17044.html</link><dc:creator>Flutist</dc:creator><author>Flutist</author><pubDate>Tue, 19 Sep 2006 02:48:00 GMT</pubDate><guid>http://www.cnitblog.com/flutist1225/articles/17044.html</guid><wfw:comment>http://www.cnitblog.com/flutist1225/comments/17044.html</wfw:comment><comments>http://www.cnitblog.com/flutist1225/articles/17044.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flutist1225/comments/commentRss/17044.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flutist1225/services/trackbacks/17044.html</trackback:ping><description><![CDATA[一、什么是动态内容  <br />大多数热门Web网站都从在线广告业务获利。Web页面中的广告空间是有限的，为了让广告投资物有所值，广告客户不仅必须在很小的广告空间内塞入大量的信息，而且还要保证广告能够吸引用户的注意力。在当前的大多数网站上，放入Web页面的横幅广告一般由服务器在构造页面的同时生成，我们无法把新的广告动态地插入到已经发送出去的页面。 如果要显示新的广告，唯一的办法就是重新刷新页面。我们可以用编程的方法刷新页面，例如： <br /><br />使用浏览器窗口对象的setTimeOut函数定期地刷新页面。但是，用这种方法刷新广告时，用户会很明显地感到页面刷新过程；同时，要确定一个合适的刷新频率也很困难。  <br />把页面的过期时间设置为数秒时间，使得无论何时输入焦点转到该页面（即浏览器被激活）时，浏览器就会重新下载该页面。  <br />一些大型网站，如yahoo.com和msn.com，都已经采用了这些技术。这两种方法都有各自的优点和缺点。在只使用Java的情况下，我们完全可以通过网络编程和一些界面编程工作实现横幅广告的刷新系统，但必须解决下载时间过长和刷新延迟的问题。  <br /><br />二、用Java实现内容推送  <br />结合JavaScript帧间通信和一个管理网络通信的Java Applet，我们能够用推送技术解决这个问题。在这样一个系统中，Java Applet的任务是连接服务器并监听内容更新。一旦接收到了新的内容，Applet就构造出显示这些新内容的HTML代码，调用一个JavaScript函数并把包含新内容的HTML传递给JavaScript函数。JavaScript函数运用DHTML和DOM技术，把页面中一个&lt;div&gt;标记的内容用参数中传入的新内容替换。由于浏览器安全的限制，Applet所打开的Socket端口只能连接到下载该Applet的服务器。  <br /><br />Web服务器只在80端口监听连接请求。因此，除了Web服务器之外，我们还需要一个接受Applet的Socket连接请求的网络应用服务。这个网络应用服务定时地查询数据库，把改动数据发布（推送）到所有已经连接的Applet。由于运用了隐藏帧和JavaScript的帧间通信功能，我们能够从用户面前隐藏大多数JavaScript逻辑。  <br /><br />在这整个处理过程中，最困难的任务是Java Applet与JavaScript代码之间的通信。Netscape提供了一个称为netscape.javascript.JSObject的类。要使用这个对象，请加入一个包含特殊“MAYSCRIPT”属性的Applet标记： <br /><br />&lt;APPLET code="MyApplet.class" height=1 width=1 MAYSCRIPT&gt;  <br /><br />JSObject的方法允许Applet与文档对象交互以及调用JavaScript命令。例如，把下面的代码放入Applet，我们就能够访问窗口对象：  <br /><br />import netscape.javascript.*; public class MyApplet extends java.applet.Applet{ private JSObject mainwin; public void init(){ mainwin = JSObject.getWindow(this); } }  <br /><br />获得JSObject引用后，我们就能够访问文档窗口对象，并通过JSObject的eval()方法调用JavaScript函数。  <br /><br />三、用DHTML更新页面  <br />在把来自Applet的新内容写入文档时，为了不影响原来已经存在的内容，我们可以使用HTML的&lt;div&gt;&lt;/div&gt;标记。这个标记在IE和Netscape中是不同的。  <br /><br />　　对于IE以及Netscape 6，这个HTML标记是：  <br /><br />// 所有要更新的内容必须用id标识 &lt;div id="iexplorer" width=700px &gt;&lt;/div&gt;  <br /><br /><br />　　对于Netscape 4.x版本，这个HTML标记是：  <br /><br />&lt;DATA&gt;&lt;layer id="netscapev" &gt;&lt;/layer&gt;&lt;/DATA&gt;  <br /><br />　　虽然我们可以通过引用适当的ID，从Applet直接更新HTML内容，但为了清楚起见，我们将把更新HTML代码的程序逻辑放入JavaScript函数。下面的JavaScript代码把浏览器的类型保存到ie变量：  <br /><br />applnname=navigator.appName; if(applnname=="Microsoft Internet Explorer") { ie=true; } else { ie=false; }  <br /><br />Applet从新数据构造出HTML代码，把它保存到JavaScript变量content，然后调用assignData()方法。内容数据可以是从纯HTML到XML到二进制数据的任何东西。  <br /><br />// 根据浏览器类型调用合适的方法 function assignData() { if(ie) {explore();} else {navig(); } }  <br /><br /><br />如果浏览器是IE或者Netscape 6，Applet调用explore()方法：  <br /><br />//content是一个javascript变量，它以HTML格式描述了需要 //显示的新数据 function explore() { iexplorer.innerHTML=content; }  <br /><br />　　如果浏览器是Netscape 4.0或者更高版本，Applet调用navig()方法：  <br /><br />function navig() { document.netscapev.document.write(“&lt;DATA&gt;“ + content + “&lt;/DATA&gt;“); document.netscapev.document.close(); }  <br /><br />四、通信过程  <br />在服务器端，一个ImageAppliation.java类的实例响应Socket连接请求，并为每一个新的连接请求创建一个新的线程。为了简化代码，每一个线程只检查数据文件是否改变。如果数据文件已经改变，则线程读取文件内容，并把新的数据发送给已经连接的Applet（示例应用把整个文件发送给Applet）。  <br /><br />在客户端，一个隐藏帧包含了ImageApplet.java这个Applet，因此用浏览器的查看HTML源代码功能是无法看到Applet标记的。Applet实现了连接服务器（下载该Applet的源服务器）的功能，并实现了一个简单的通信协议。建立与服务器的连接之后，Applet接收来自服务器的数据，构造出HTML代码，并调用JavaScript函数把数据传入文档：  <br /><br />public void upDateHTML(String str){ //data是表单的名字， //quote是一个JavaScript变量 //str是新构造出来的HTML代码 mainwin.eval("document.data.quote.value=“" + str + "“"); mainwin.eval("javascript:assignData()"); return; }  <br /><br />netscape.javascript.JSObject完成Applet到JavaScript的通信，不同版本的客户端浏览器需要不同的版本。你可以下载得到为Netscape提供的压缩类文件java40.jar。IE已经带有JSObject类，但有点难找。你可以搜索$windows$\Java\Packages目录寻找包含JSObject类的ZIP文件。  <br /><br />服务器把ImageArrayElement.java类的实例通过toString()方法串行化成为字符串发送给Applet。服务器从数据文件构造出各个对象，调用toString()方法，连接得到代表所有对象的字符串，最后发送结果字符串。而在另一端，Applet接收并解析这个字符串，重新构造出各个ImageArrayElement对象。这里之所以用一个长字符串的形式发送数据，是因为这种方法只需要很简单的处理过程，使得用户能够以接近实时的速度立即得知数据的变化；但是，我们也可以用另外一种方法，即以向量的形式发送对象。  <br /><br />在一个正式运行的应用中，你一般应该让新数据插入当前页面的过程透明。但在示例应用中，为了让程序运行过程更加直观，它将在新内容到达的时候提示用户。  <br /><br />推送技术最主要的优点就是应用服务器只把那些改变的数据发送到网络，从而使得延迟减到了最少。由于这个Applet负责完成的工作非常少（不涉及用户界面，这部分工作由浏览器负责），所以Applet体积很小，装载速度非常快。  <br /><br />五、如何运行本文实例  <br />要测试本文示例应用，你的机器上必须安装有Web服务器和JDK 1.7或更高版本。  <br /><br />安装要点：  <br /><br />解开ZIP压缩文件并安装到Web服务器默认根目录。  <br />对于IIS服务器，默认根目录是Inetput\wwwroot  <br />对于jsdk2.1所带的免费服务器，默认目录是&lt;安装目录&gt;\webpages  <br />解开压缩文件之后，所有文件都将安装到&lt;Web服务器根&gt;/exp/目录。  <br />把下面几行代码加入默认页面。每一种服务器都有自己的默认页面，IIS的默认页面是“default.htm”，请参见Web服务器文档了解具体说明：  <br /><br />&lt;ul&gt;&lt;li&gt; &lt;a href="/exp/ImageMain.htm"&gt; Java based dynamic Ad-Banner&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  <br /><br />运行应用的步骤：  <br /><br />打开一个DOS窗口，进入&lt;默认Web目录&gt;/exp，执行“java ImageApplication”。系统将显示“Server started listening at port 6011”。注意确保classpath环境变量指向了当前工作目录。  <br />启动Web服务器。  <br />打开浏览器输入下面的URL：http://localhost:8080。该URL将打开Web服务器的默认页面，它应该有一个“Java based dynamic Ad-Banner”链接。点击这个链接就启动了本文的示例应用。  <br />用Notepad打开“/exp/images.txt”文件，复制并粘贴一行内容，保存文件。你可以立即看到系统显示一个JavaScript窗口提示内容更新。关闭JavaScript窗口，页面将显示新的内容。  <br /><img src ="http://www.cnitblog.com/flutist1225/aggbug/17044.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flutist1225/" target="_blank">Flutist</a> 2006-09-19 10:48 <a href="http://www.cnitblog.com/flutist1225/articles/17044.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Server Push详解</title><link>http://www.cnitblog.com/flutist1225/articles/16835.html</link><dc:creator>Flutist</dc:creator><author>Flutist</author><pubDate>Thu, 14 Sep 2006 06:18:00 GMT</pubDate><guid>http://www.cnitblog.com/flutist1225/articles/16835.html</guid><wfw:comment>http://www.cnitblog.com/flutist1225/comments/16835.html</wfw:comment><comments>http://www.cnitblog.com/flutist1225/articles/16835.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/flutist1225/comments/commentRss/16835.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/flutist1225/services/trackbacks/16835.html</trackback:ping><description><![CDATA[
		<p>服务器推送(Server Push) </p>
		<p>推送技术的基础思想是将浏览器主动查询信息改为服务器主动发送信息。服务器发送一批数据，浏览器显示这些数据，同时保证与服务器的连接。当服务器需要再次发送一批数据时，浏览器显示数据并保持连接。以后，服务器仍然可以发送批量数据，浏览器继续显示数据，依次类推。 </p>
		<p>客户端拉曳(Client Pull) </p>
		<p>在客户端拖曳技术中，服务器发送一批数据，在HTTP响应或文档头标记中插入指令，让浏览器“在5秒内再次装入这些数据”或“10秒内前往某URL装入数据”。当指定的时间达到时，客户端就按照服务器的指示去做，或者刷新当前数据，或者调入新的数据。 </p>
		<p>其实push 和 pull 这两种技术手段非常不同，但目的几乎一致，都是为了给最终用户方便的提供最新信息。 </p>
		<p>在服务器推送技术中，HTTP 连接一直保持着，直到服务器知道自己已结束发送数据并发送一个结束信号，或者客户端中断连接。而在客户端拖曳技术中，并不保持HTTP连接，相反，客户端被告知合时建立新连接，以及建立连接是获取什么数据。 </p>
		<p>在服务器推送中，奇妙之处在于“multipart/mixed”格式的MIME，它能够使一个报文（或HTTP响应）包含许多数据项、在客户端拖曳中，奇妙之处在于HTTP响应头标（或等效的HTML元素），它能告知客户端在指定的延时时间后执行何种动作。 </p>
		<p>服务器推送通常效率要比客户端拖曳效率高，因为它不必为后续数据建立新的连接。由于始终保持连接，即使没有数据传输时也是这样，因此服务器必须愿意分配这些TCP/IP端口，对于TCP/IP端口数有限的服务器这将是一个严重的问题。 </p>
		<p>客户端拖曳效率低，因为这必须每次为传送数据建立新的连接。但是它不必始终保持连接。 </p>
		<p>在实际情况中，建立HTTP连接通常需要花费相当多的时间，多达一秒甚至更多。因此从性能上考虑，服务器推送对于最终用户更有吸引力，特别是对于需要经常更新信息的情况下。 </p>
		<p>服务器推送相对客户端拖曳的另一点优势是，服务器推送相对比较容易控制。例如，服务器每一次推送时都保持一个连接，但它又随时可以关闭其中的任何连接，而不需要在服务器上设置特殊的算法。而客户端拖曳在同样的情况下要麻烦许多，它每次要与服务器建立连接，服务器为了处理将客户端拖曳请求与特定的最终用户匹配等情况，需要使用相当麻烦的算法。 </p>
		<p>如果实现服务器推送的CGI程序是使用Shell脚本语言编写的，有时会存在一些问题。例如，客户端最终用户中断连接，Shell程序通常不能注意到，这将使资源毫无用处的浪费掉，解决这一问题的办法是用Perl或者C来编写这类CGI程序，以使用户中断连接时能够结束运行。 </p>
		<p>
				<br />如上所述，在服务器推送中，多个响应中连接始终保持，使服务器可在任何时间发送更多的数据。一个明显的好处是服务器完全能够控制更新数据的时间和频率。另外，这种方法效率高，因为始终保持连接。缺点是保持连接状态会浪费服务器端的资源。服务器推送还比较容易中断。 </p>
		<p>接下来就大概说说服务器推送技术 <br />服务器在响应请求时，HTTP使用MIME报文格式来封装数据。通常一个HTTP响应只能包含一个数据块。但MIME有一种机制可用一个报文（或HTTP响应）表示将多个数据块，这种机制就是成为“multipart/mixed”的标准MIME类型。multipart/mixed报文大体格式如下： <br />Content-type:multipart/mixed;boundary=ThisRandomString <br />--ThisRandomString <br />Content-type:text/plain <br />第一个对象的数据。 <br />--ThisRandomString <br />Content-type:text/plain <br />第二个对象的数据。 <br />--ThisRandomString-- </p>
		<p>上述报文包括两上数据块，二者的类型都是“text/plain”。最后一个“ThisRandomString”后的两条短线（--）表示报文结束，后面没有数据。 </p>
		<p>对于服务器推送，使用一个“multipart/mixed”类型的变种--multipart/x-mixed-replace。这里，“x-”表示属于实验类型。“replace”表示每一个新数据块都会代替前一个数据块。也就是说，新数据不是附加到旧数据之后，而是替代它。 </p>
		<p>下面是实际使用的“multipart/x-mixed-replace”类型： <br />Content-type:multipart/x-mixed-replace;boundary=ThisRandomString <br />--ThisRandomString <br />Content-type:text/plain <br />第一个对象的数据 <br />--ThisRandomString <br />Content-type:text/plain <br />第二个（最后一个）对象的数据。 <br />--ThisRandomString-- <br />使用这一技术的关键是，服务器并不是推送整个“multipart/x-mixed-replace”报文，而是每次发送后数据块。 <br />HTTP连接始终保持，因而服务器可以按自己需要的速度和频率推送新数据，两个数据块之间浏览器仅需在当前窗口等候，用户甚至可以到其他窗口做别的事情，当服务器需要发送新数据时，它只是源（ABC输入法没那个字*&amp;^$#）传输管道发送数据块，客户端相应的窗口进行自我更新。 </p>
		<p>在服务器推送技术中，“multipart/x-mixed-replace”类型的报文由唯一的边界线组成，这些边界线分割每个数据块。每个数据块都有自己的头标，因而能够指定对象相关的内容类型和其他信息。由于“multipart/x-mixed-replace”的特性是每一新数据块取代前一数据对象，因而浏览器中总是显示最新的数据对象。 <br />“multipart/x-mixed-replace”报文没有结尾。也就是说，服务器可以永远保持连接，并发送所需的数据。如果用户不再在浏览器窗口中显示数据流，或者浏览器到服务器间的连接中间（例如用户按“STOP”按钮），服务器的推送才会中断。这是人们使用服务器推送的典型方式。 </p>
		<p>当浏览器发现“Content-type”头标或到达头标结束处时，浏览器窗口中的<font style="BACKGROUND-COLOR: #ff1493">前一个文档被清除</font>（注1），并开始显示下一个文档。发现下一个报文边界时，就认为当前数据块（文档）已经结束。 <br />总之，服务器推送的数据由一组头标（通常包括“Content-type”）、数据本身和分割符（报文边界）三部分组成。浏览器看到分割符时，它保持状态不变，直到下一个数据块到达。 </p>
		<p>将以上概念进行用编程方法实现，就可以得到实际的服务器推送程序。例如，下面的Unix shell程序将使浏览器每5秒显示一次服务器上的进程列表： <br />#!/bin/sh <br />echo "HTTP/1.1 200" <br />echo "Content-type: multipart/x-mixed-replace;boundary=--ThisRandomString--" <br />echo "" <br />echo "--ThisRandomString--" <br />while true <br />do <br />echo "Content-type: text/html" <br />echo "" <br />echo "h2Processes on this machine updated every 5 seconds/h2" <br />echo "time:" <br />date <br />echo "p" <br />echo "plaintext" <br />ps -el <br />echo "--ThisRandomString--" <br />sleep 5 <br />done <br /><br />注意到，边界设置在sleep语句之前发送，这能够确保浏览器清除其缓冲区，并显示所接收到的最新数据。 <br />NCSA HTTPD用户在内容类型中不能使用空格，包括边界参数。NCSA HTTPD只能将不带空格字符的字符串作为内容类型。如果在内容类型行中存在空格（冒号后面的空格除外），空格后的任何文本都会被删除。 <br />下面的示例是正确的： <br />Content-type: multipart/x-mixed-replace;boundary=ThisRandomString <br />而下例则不能正常工作，因为它在中间有空格： <br />Content-type: multipart/x-mixed-replace; boundary=ThisRandomString <br />服务器推送的另一个优点是它可以针对单个内联图象进行。包括图象的文档可以由服务器定时或定周期进行更新。而实现这一点非常简单：只需使IMG元素的SRC属性指向推送一系列图象的URL即可。 </p>
		<p>如果服务器推送用于单个内联图象，文档中的图象就会一次次被新推送来的图象所代替，而文档本身不需变化（假设文档没有进行服务器推送）。这样，WEB页面中有限的动画就可以为静态画面所代替。 </p>
		<p>客户端拖曳 </p>
		<p>客户端拖曳的一个简单用法是使文档按固定周期自动重载。例如，考虑下面的HTML文档： <br />&lt;META HTTP-EQUIV="Refresh" CONTENT=1&gt; <br />&lt;TITLE&gt;Document ONE&lt;/TITLE&gt; <br />&lt;H1&gt;This is Document ONE!&lt;/H1&gt; <br />Here's some text.&lt;P&gt; <br />如果将它载入支持动态文档的浏览器（Netscape 1.1以上，Internet Explorer和Mosaic也支持客户端拖曳），它将每隔一秒将自己重载一次。 <br />由于META元素实际是在HTML文档中模拟HTTP响应头标，所以它能够告知浏览器将自身信息当作HTTP响应使用。上例中的META标记相当于： <br />Refresh:1 <br />这样，实际上就是HTTP头标告知浏览器每一秒更新一次文档。如果需要延时是12秒，那么就是这样的指令： <br />&lt;META HTTP-RQUIV="Refresh" CONTENT=12&gt; <br />那么它等效于： <br />Refresh:12 </p>
		<p>关于客户端的拖曳我也懒的继续写下去，关于怎么使客户端自动申请其他URL的数据话，请使用如下： <br />&lt;META HTTP-EQUIV="Refresh" CONTENT="12;URL=http://www.cnitblog.com/flutist1225"&gt; <br />注意的是，此处的URL不能使用相对路径，必须全部指定。 </p>
		<p>其中时间间隔可以设置为0，这样浏览器在当前文档显示完毕后，以最快的速度载入新的数据！<br />附录一<br />C语言nph-Hello.c<br />#include &lt;stdio.h&gt;<br />int main()<br />{<br />int i;<br />printf("HTTP/1.1 200\n");<br />printf("Content-type: multipart/x-mixed-replace;boundary=--ThisString--\n\n");<br />fflush(stdout);<br />printf("--ThisString--\n");</p>
		<p>for(i=0;i&lt;30;i++)<br />    {<br />        printf("Content-type:text/html;\n\n");<br />        printf("hello i=%i\n",i);  //注2.<br />        fflush(stdout);<br />        printf("--ThisString--\n");<br />        sleep(10);<br />    }<br />        return 0;<br />}<br />//注1：本人测试IE6不支持这种清除上次显示内容，firefox支持，两种浏览器显示效果不同<br />//注2：因为服务器的输出缓冲区原因可能存在第一次显示的比较慢的现象，为了达到测试效果可以将printf("hello i=%d\n",i)；替换为system("ps -ajx");这样观看的效果将非常明显.<br />//注3：对于server-push的支持，目前只知道IIS和APACHE,其它web服务器咱未做测试<br /><br /></p>
<img src ="http://www.cnitblog.com/flutist1225/aggbug/16835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/flutist1225/" target="_blank">Flutist</a> 2006-09-14 14:18 <a href="http://www.cnitblog.com/flutist1225/articles/16835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>