关于WebSocket技术浅析

WebSocket技术,是用于服务端与浏览器端的基于TCP/IP的会话协议所兴起的一项技术 但凡TCP/IP协议都会经过三次握手,而后进行会话数据的传输。保证数据的可靠性(在网络技术发达的今天,这点已经再也不是问题了) 此项技术放弃了之前的须要定时给服务器发送请求。由服务器刷新数据,而后返回给客户端,这样大大的减小了服务器的负担 咱们如何去实现WebSocketjavascript

我用的环境为 jdk1.7+ Tomcat 7.0.52 服务引用的主要Jar包为 catalina.jar,websocket-api.jar 全来自tomcat/lib下 服务端代码以下:html

package com.zx.websocket;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户链接的终端访问URL地址,客户端能够经过这个URL来链接到WebSocket服务器端
 */
@ServerEndpoint(value="/singlewebsocket")
public class WebSocketSingleTest {
	//静态变量,用来记录当前在线链接数。应该把它设计成线程安全的。
    private static Integer onlineCount = 0;
    //concurrent包的线程安全Map,能够使用Map来存放,其中Key能够为用户标识
    private static Map<Session, WebSocketSingleTest> map=new ConcurrentHashMap<Session, WebSocketSingleTest>();
	//声明这是用户打开链接处理的方法
    @OnOpen
	public void OnOpen(Session session) throws IOException
	{
		System.out.println("有新用户连入!session info is :"+session.getId());
		synchronized (onlineCount) {
			addOnlineCount();//在线用户加1 此方法同步
		}
		map.put(session, this);//添加用户信息
		Collection key=map.keySet();
		Iterator it=key.iterator();
		String ids="";
		while(it.hasNext()){
			ids+=((Session)it.next()).getId()+",";
		}
		session.getBasicRemote().sendText(ids);
	}
    //声明这是用户关闭链接处理的方法
	@OnClose
	public void OnClose(Session session)
	{
		System.out.println("有用户退出!用户ID is :"+session.getId());
		synchronized (onlineCount) {
			reduiceOnlineCount();//在线用户减1 此方法同步
		}
		map.remove(session);//移除用户信息
	}
	//声明这是异常处理的方法
	@OnError
    public void onError(Session session, Throwable error){
        System.out.println("发生错误");
        error.printStackTrace();
    }
	//声明这是用户发送消息的方法
	@OnMessage
	public void OnMessage(String message,Session session)
	{
		System.out.println("来自客户端的消息:["+message+"]");
		/**
		 * 获取消息后,读取message获取传输消息的目标人,根据session的Id能够遍历Map集合  获取Map的对应的Socket类
		 * 而后在由这个Socket类 发送消息 参见sendMessage
		 * 注:目标人消息应该经过Message从前台传递过来,再由后台遍历处理
		 */
	}
	public void sendMessage(Session session,String message) throws IOException
	{
		session.getBasicRemote().sendText(message);
	}
	public static int getOnlineCount() {
		return onlineCount;
	}
	public static void setOnlineCount(int onlineCount) {
		WebSocketSingleTest.onlineCount = onlineCount;
	}
	public synchronized void addOnlineCount()
	{
		WebSocketSingleTest.onlineCount++;
		
	}
	public synchronized void reduiceOnlineCount()
	{
		WebSocketSingleTest.onlineCount--;
		
	}
}

Jsp端主要JS代码以下:java

<%@ page language="java" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>Java后端WebSocket的Tomcat实现</title>
</head>
<body>
    Welcome<br/><input id="text" type="text"/>
    <button onclick="send()">发送消息</button>
    <hr/>
    <button onclick="closeWebSocket()">关闭WebSocket链接</button>
    <hr/>
    <div id="message"></div>
</body>

<script type="text/javascript">
    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://localhost:8080/websocket/zxwebsocket");
    }
    else {
        alert('当前浏览器 Not support websocket')
    }

    //链接发生错误的回调方法
    websocket.onerror = function () {
        setMessageInnerHTML("WebSocket链接发生错误");
    };

    //链接成功创建的回调方法
    websocket.onopen = function () {
        setMessageInnerHTML("WebSocket链接成功");
    }

    //接收到消息的回调方法
    websocket.onmessage = function (event) {
        setMessageInnerHTML(event.data);
    }

    //链接关闭的回调方法
    websocket.onclose = function () {
        setMessageInnerHTML("WebSocket链接关闭");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket链接,防止链接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
        closeWebSocket();
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //关闭WebSocket链接
    function closeWebSocket() {
        websocket.close();
    }

    //发送消息
    function send() {
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
</script>
</html>

这样一个消息推送机制就完成了web

其中发布的时候我碰到的一些问题,在第一次访问的时候, 服务器后台会抱一个错,这个错是一个类型转换异常, DefaultInstanceManager cannot be cast to InstanceManager 百度后知道, 在发布的时候tomcat会将 catalina.jar包加到项目的web-inf下面的lib文件夹下面,这样这个包就会和tomcat下面的lib下面的catalina.jar 包冲突会报java.lang.ClassCastException 解决方案一:在部署的时候 须要在发布后的项目WEB-INF/lib下去掉catalina.jar和websocket-api.jar 解决方案二:修改了tomcat里的context.xml文件,在context 元素下添加<Loader delegate="true" />后端

相关文章
相关标签/搜索