基于Web的数据推送技术
对于实时性数据显示要求比较高的系统,比如竞价,股票行情,实时聊天等,我们的解决方案有以下几种。
1. HTTP请求发送模式,一般可以基于ajax的请求,比如每3秒一次访问下服务器,实现过程比较简单,只要需求不是太变态,基本上认为这个时间延迟可以接 受的话,那完全没有问题,不过服务端的压力有点大,访问量多的话,那就很容易挂了,这个也是为什么很多聊天室有人数限制的原因了,我怀疑一个聊天室就有一 台服务器撑着。2.基于socket的推送方式,这个是真正的推送技术,服务器压力相对较小,但是要保持和客户端通讯的socket,以 便需要的时候可以拿到这个socket给用户发送消息。但是保持那么的socket也是耗资源的。而且郁闷的是我们的网页是不支持socket接受消息 的,不过可以通过flash或者applet来作为socket的客户端,他们都是可以嵌入到网页中的。浏览器的支持类型来说,还是flash会更友好 点。 下面给个例子,是服务器端的,主要功能是每3秒钟向客户端推送个时间 Server.java----------------------------------------------/** * */ package com.spell;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.Timer;/** * @author Administrator * */ public class Server { private int PORT = 9000;private ServerSocket ss = null;private Timer timer = new Timer(); public Server() { try { ss = new ServerSocket(PORT);System.out.println("server start");} catch (IOException e) { e.printStackTrace();}} /** * @param args */public static void main(String[] args) { Server server = new Server();server.startup(); } public void startup() { Socket s = null;while (true) { try { s = ss.accept();Handler handler = new Handler(s);timer.schedule(handler, 1000, 3000);} catch (IOException e) { e.printStackTrace();}}}}Handler.java处理具体的事务-----------------------------------------/** * */ package com.spell;import java.io.IOException;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;import java.util.Date;import java.util.TimerTask;/** * @author Administrator * */ public class Handler extends TimerTask { private Socket socket; public Handler(Socket socket) { this.socket = socket; } @Overridepublic void run() { String nowTime = (new Date()).toLocaleString();try { if (socket != null && socket.isConnected()) { // 这里打个擦边球,先发送个紧急的数据包,如果发送发送了异常,说明客户端已经关闭了socket连接了,进入异常处理程序socket.sendUrgentData(0xFF);System.out.println(nowTime);PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));pw.append(nowTime);pw.append("\r");pw.flush();}} catch (IOException e) { try { socket.close();} catch (IOException e2) { }this.cancel();} }} applet程序: -------------------------------------------------/** * */ package com.spell;import java.applet.Applet;import java.awt.Label;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.Socket;/** * 此程序eclipse运行良好,但是在IE中引入该Applet就出错了,提示access denied * 是由于客户端的安全策略引起的,看来还是要用flash比较靠谱 * */ public class SocketApplet extends Applet implements Runnable { Label text = new Label();private Socket socket;private BufferedReader br; public SocketApplet() { } public void init() { text.setText("time begin");add(text);try { socket = new Socket("172.21.1.112", 9000);// socket = new Socket("127.0.0.1", 9000);br = new BufferedReader(new InputStreamReader(socket.getInputStream()));text.setText("socket setup ok ...");// 初始化完毕,启动线程处理new Thread(this).start();} catch (Exception e) { text.setText(e.getMessage());}} public void run() { while (true) { try { text.setText(br.readLine());} catch (IOException e) { }}}} ---flash socket的解决方案flex代码:<?xml version="1.0" encoding="utf-8"?><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:Declarations><!-- 将非可视元素(例如服务、值对象)放在此处 --></fx:Declarations><s:Label x="157" y="98" text="my time" height="22" width="230" id="message"/><s:Button x="153" y="126" label="begin socket" id="btn" click="changeText()"/><s:Button x="153" y="155" label="end socket" id="btn2" enabled="false" click="endSocket()"/><fx:Script><![CDATA[var mysocket:Socket;var host:String="127.0.0.1";var str:String;var port:int=9000;public function changeText():void { btn.enabled=false;btn2.enabled=true;mysocket=new Socket();mysocket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );mysocket.connect(host,port);}private function onSocketData( event:ProgressEvent ):void { trace( "Socket received " + mysocket.bytesAvailable + " byte(s) of data:" );var data:String = mysocket.readUTFBytes(mysocket.bytesAvailable);message.text=data;}public function endSocket():void { mysocket.close();btn.enabled=true;btn2.enabled=false;}]]></fx:Script></s:Application>概念引申阅读:http://www.javaeye.com/topic/701526