关于使用WebSocket的一点经验

一、 WebSocket介绍:

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

二、传统的Ajax 轮询代码

下面是script中写的Ajax轮询方法
Ajax方法写好后,要调用Window setInterval() 这个方法,数值以毫秒计算。

function getEvents(){
	$.ajax({
		async: false,
		type: "get",
		url: url,
		dataType: "json",
		success(data) {
		
						//返回后的数据处理。
				)
			}
		}
	})
}
getEvents();			//页面加载便执行方法
setInterval(function(){
	getEvents();
},15000);				//每15秒执行一次。

三、 WebSocket持续推送。

页面代码:

	<input id="text" type="text"/>
	<button onclick="send()">发送消息</button>
	<hr/>
	<button onclick="closeWebSocket()">关闭WebSocket连接</button>
	<hr/>
	<div id="message"></div>
	
	<script>代码:
		var websocket = null;
		//判断当前浏览器是否支持WebSocket
		if('WebSocket' in window){
			//连接WebSocket节点访问后台的URL路径,002是参数。
			websocket = new WebSocket("ws://localhost:8080/admin/productWebSocket");
		}
		else{
			alert('Not support websocket')
		}
		//连接发生错误的回调方法
		websocket.onerror = function(){
			setMessageInnerHTML("error");
		};
		//连接成功建立即执行的方法
		websocket.onopen = function(event){
			setMessageInnerHTML("open");//调用下面的方法。
		}
		//接收到消息的回调方法
		websocket.onmessage = function(event){
			setMessageInnerHTML(event.data);
		//对数据进行处理。
		}
		//连接关闭的回调方法
		websocket.onclose = function(){
			setMessageInnerHTML("close");
		}
		//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
		window.onbeforeunload = function(){
			websocket.close();
		}
		//将消息显示在网页上
		function setMessageInnerHTML(innerHTML){
				document.getElementById('message').innerHTML += innerHTML + '<br/>';
		}
		//发送消息
		function send(){
			var message = document.getElementById('text').value;
			websocket.send(message);
		}
		//关闭连接
		function closeWebSocket(){
			websocket.close();
		}
		

后台 WebSocket代码:


@Component
@ServerEndpoint(value = "/admin/productWebSocket", configurator = MyEndpointConfigure.class)
public class ProductWebSocket {
    // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static final AtomicInteger OnlineCount = new AtomicInteger(0);
    // concurrent包的线程安全Set,用来存放每个客户端对应的ProductWebSocket对象。
    private static CopyOnWriteArraySet<ProductWebSocket> webSocketSet = new CopyOnWriteArraySet<ProductWebSocket>();
    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    private Logger log = LoggerFactory.getLogger(ProductWebSocket.class);

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(@PathParam("userId")String titleId, Session session) {
        log.info("新客户端连入,用户id:" + titleId);//titleId 便是后面跟的002参数
        ProductWebSocket client = new ProductWebSocket();
        client.session = session;
        client.webSocketSet = webSocketSet;
        client.carId=titleId;
     	 if("002".equals(titleId)) {
            webSocketSet.add(client); // 加入set中
        }
        System.out.println("-当前在线人数为:"+getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        log.info("一个客户端关闭连接");
        for (ProductWebSocket productWebSocket : webSocketSet) {
            if (productWebSocket.session.equals(session)) {
                webSocketSet.remove(productWebSocket);
            }
        }
    }
    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     *            客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("用户发送过来的消息为:"+message);
		//群发消息
		for(ProductWebSocket item: webSocketSet){
		try {
		item.sendMessage(message);
		} catch (IOException e) {
		e.printStackTrace();
		continue;
		}
}

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("websocket出现错误");
        error.printStackTrace();
    }

    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
            log.info("推送消息成功,消息为:" + message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 群发自定义消息
     */
    public static void sendInfo(String message) throws IOException {
        for (ProductWebSocket productWebSocket : webSocketSet) {
            productWebSocket.sendMessage(message);
        }
    }
    public static synchronized int getOnlineCount() {
        return OnlineCount.get();
    }

    public static synchronized void addOnlineCount() {
        OnlineCount.incrementAndGet(); // 在线数加1
    }

    public static synchronized void subOnlineCount() {
        OnlineCount.decrementAndGet(); // 在线数加1
    }

}

以上便是使用WebSocket的一点经验,代码多变,方法也不尽相同。仅留作日后参考。
有错误还请大家指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章