web消息推送技术

来源:互联网 发布:mac下python开发环境 编辑:程序博客网 时间:2024/06/05 11:12

最近在做一个web项目,有个需求是服务器向客户端发送数据,一般来讲,web是请求响应方式是无法做到服务端直接给客户端发送数据的。第一想到的是轮询方法,让客户端不断刷新访问服务器。

这种方法缺点是刷新频率不好控制,设置高了会给服务器造成很大负担,相反,消息得不到及时更新。


目前,我找到两种较优的方法。

1 . comet 技术 ——基于长连接的技术

在传统轮询方法上做的改进。

客户端和服务器保持一个长连接,当服务器向客服端发送消息,才响应数据。这种解决方案,可以说是无奈之举。

参考DWR框架

2. websocket技术 ——基于双向传输技术

html5就提供了这种技术的支持。

我就尝试了第二种方案,结合网友代码在tomcat7.0上做的例子,仅供参考!


index.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"    pageEncoding="utf-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><script type="text/javascript" src="js/jquery-1.11.2.js"></script><script type="text/javascript" src="js/socket.js"></script><title>Insert title here</title></head><body>   <table>  <tr>    <td>Message</td>    <td><input type="text" id="message"></td>  </tr>  <tr>    <td>Name</td>    <td><input type="text" id="othername"></td>  </tr>  <tr>    <td><input id="sendbutton" type="button" value="send" onClick="click"  disabled="true">      </input></td>  </tr></table></body></html>
js/jsocket.js

var username = window.prompt("输入你的名字:");document.write("Welcome<p id=\"username\">"+username+"</p>");if (!window.WebSocket && window.MozWebSocket)    window.WebSocket=window.MozWebSocket;if (!window.WebSocket)    alert("No Support ");var ws;$(document).ready(function(){         $("#sendbutton").attr("disabled", false);     $("#sendbutton").click(sendMessage);    startWebSocket();})function sendMessage(){    var othername=$("#othername").val();    var msg="MSG\t"+username+"_"+othername+"_"+$("#message").val();    send(msg);}function send(data){    console.log("Send:"+data);    ws.send(data);}function startWebSocket(){        ws = new WebSocket("ws://" + location.host + "/web_socket/websocket/test");    ws.onopen = function(){        console.log("success open");        $("#sendbutton").attr("disabled", false);    };     ws.onmessage = function(event)     {         console.log("RECEIVE:"+event.data);         handleData(event.data);      };      ws.onclose = function(event) {     console.log("Client notified socket has closed",event);   };   }function handleData(data){    var vals=data.split("\t");    var msgType=vals[0];    switch(msgType)    {    case "NAME":        var msg=vals[1];        var mes="NAME"+"\t"+msg+"_"+ username;        send(mes);        break;    case "MSG":        var val2s=vals[1].split("_");        var from=val2s[0];        var message=val2s[2];        alert(from+":"+message);        break;    default:        break;                }}

web.xml

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">  <display-name>web_socket</display-name>  <welcome-file-list>    <welcome-file>index.html</welcome-file>    <welcome-file>index.htm</welcome-file>    <welcome-file>index.jsp</welcome-file>    <welcome-file>default.html</welcome-file>    <welcome-file>default.htm</welcome-file>    <welcome-file>default.jsp</welcome-file>  </welcome-file-list>    <servlet>        <servlet-name>wsSnake</servlet-name>        <servlet-class>cn.eaglestart.websocket.MyWebSocketServlet</servlet-class>      </servlet>      <servlet-mapping>        <servlet-name>wsSnake</servlet-name>        <url-pattern>/websocket/test</url-pattern>      </servlet-mapping>          </web-app>

MyMessageInbound.java

package cn.eaglestart.websocket;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.util.Set;import java.util.concurrent.CopyOnWriteArraySet;import org.apache.catalina.websocket.MessageInbound;import org.apache.catalina.websocket.WsOutbound;public class MyMessageInbound  extends MessageInbound{private String username;private Set<MyMessageInbound> users = new CopyOnWriteArraySet<MyMessageInbound>(); public static int USERNUMBER = 1;public MyMessageInbound(Set<MyMessageInbound> users) {super();this.users = users;}@Overrideprotected void onBinaryMessage(ByteBuffer arg0) throws IOException {// TODO Auto-generated method stub}@Overrideprotected void onTextMessage(CharBuffer arg0) throws IOException {String data = arg0.toString(); System.out.println("data:" + data);         String[] val1 = data.split("\\t");                  if(val1[0].equals("NAME"))         {             String[] val2=val1[1].split("_");             for(MyMessageInbound user:users){                 if (user.username.equals(val2[0])){                     user.username=val2[1];                 }             }         }         else if(val1[0].equals("MSG"))         {             String[] val2=val1[1].split("_");             for(MyMessageInbound user:users){                 if (user.username.equals(val2[1])){                     try {                         CharBuffer temp=CharBuffer.wrap(data);                         user.getWsOutbound().writeTextMessage(temp);                     } catch (IOException e) {                         // TODO Auto-generated catch block                         e.printStackTrace();                     }                 }             }                 }         else         {             System.out.println("ERROR");         }     }@Overrideprotected void onOpen(WsOutbound outbound) {// TODO Auto-generated method stub  // this.connection=connection;        this.username = "#" + String.valueOf(USERNUMBER);        System.out.println(username);        USERNUMBER++;        try {            String message = "NAME" + "\t" + this.username;            CharBuffer buffer = CharBuffer.wrap(message);            this.getWsOutbound().writeTextMessage(buffer);        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        users.add(this);} public void onMessage(String data) { System.out.println("data:" + data);         String[] val1 = data.split("\\t");                  if(val1[0].equals("NAME"))         {             String[] val2=val1[1].split("_");             for(MyMessageInbound user:users){                 if (user.username.equals(val2[0])){                     user.username=val2[1];                 }             }         }         else if(val1[0].equals("MSG"))         {             String[] val2=val1[1].split("_");             for(MyMessageInbound user:users){                 if (user.username.equals(val2[1])){                     try {                         CharBuffer temp=CharBuffer.wrap(data);                         user.getWsOutbound().writeTextMessage(temp);                     } catch (IOException e) {                         // TODO Auto-generated catch block                         e.printStackTrace();                     }                 }             }                 }         else         {             System.out.println("ERROR");         }     } @Override     protected void onClose(int status) {         users.remove(this);     }}

MyWebSocketServlet.java

package cn.eaglestart.websocket;import java.util.Set;import java.util.concurrent.CopyOnWriteArraySet;import javax.servlet.http.HttpServletRequest;import org.apache.catalina.websocket.StreamInbound;import org.apache.catalina.websocket.WebSocketServlet;public class MyWebSocketServlet  extends WebSocketServlet{ public final Set<MyMessageInbound> users = new CopyOnWriteArraySet<MyMessageInbound>();    public static int USERNUMBER = 1;@Overrideprotected StreamInbound createWebSocketInbound(String arg0,HttpServletRequest arg1) {System.out.println("=====init====");// TODO Auto-generated method stubreturn new MyMessageInbound(users);}}

参考代码链接如下
html5利用websocket完成的推送功能


1 0