Java的WebSocket实现

一、WebSocket的简单实现

     随着互联网的发展,传统的http协议已经很难满足web应用日益复杂的需求了,近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,拓展了浏览器与服务端的通信功能,使服务端也能够主动的向客户端发送数据

     传统的http协议是无状态的,每次请求(request)都要由客户端(如:浏览器)主动发起,服务端处理后返回respone结果,而服务端很难主动向客户端发送数据,这种客户端是主动方,服务端是被动方的传统web模式,对于信息变化不频繁的web应用来说造成的麻烦较小,而对于涉及实时信息的Web应用造成了很大的不便,比如即时通信,实时数据,订阅推送等等功能。在WebSocket规范提出之前,开发人员如果需要实现这些实时性比较强的功能,经常会使用折中的办法:轮询(polling) 和 Comet技术,其实后者本质也是一种轮询,只不过有所改进

     轮询是最原始的实时的Web应用的解决方案,轮询技术要求客户端以设定的时间间隔周期性的向服务端发送请求,频繁的查询是否有新的数据改动,明显的这种方法会导致过多不必要的请求。浪费流量和服务器资源。

     Comet技术又可以分为长轮询和流技术。长轮询改进了上述的轮询技术,减小了无用的请求,他会为某些数据设定过期的时间,当数据过期之后才会向服务端发送请求,这种机制适合数据的改动不是特别频繁的情况,流技术通常是指客户端使用一个隐藏得窗口与服务器端建立一个http长连接,服务端会不断更新连接状态以保持http长连接存活,这样的话,服务器端就可以通过这条长连接主动将数据发送给客户端,流技术在大并发环境下,可能会考验到服务端的性能。

     这两种技术都是基于请求 - 应答模式,都不算真正意义上的实时技术,它们的每一次请求,应答都浪费了一定流量在相同的头部信息上,并且开发复杂度也比较大。

     伴随着HTML5推出的websocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能力,WebSocket的工作流程是这样的

  1. 浏览器通过JavaScript 向服务器端发出建立WebScoket连接的请求,连接建立成功之后
  2. 客户端和服务端就可以通过TCP连接传输数据因为WebSocket连接本质时TCP,所以不需要每次传输都带上重复的头部数据,所以数据传输比轮询和Comet技术小了很多。

二、WebSocket实例

2.1 新建JavaWeb测试项目

Java的WebSocket实现_第1张图片

 

在POM.xml中添加jar包依赖

        
            javax.websocket
            javax.websocket-api
            1.1
            provided
        

客户端(Web)代码

1. HTML部分





2.Javascript 部分

JavaWeb后端代码

package com.gss.socket;


import com.sun.istack.internal.logging.Logger;

import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@ServerEndpoint(value = "/websocket")
public class WebSocketTest {

    private static Logger logger = Logger.getLogger(WebSocketTest.class);
    //线程安全的静态变量,表示在线连接数
    private static volatile int onlineCount = 0;

    //用来存放每个客户端对应的WebSocketTest对象,适用于同时与多个客户端通信
    public static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();
    //若要实现服务端与指定客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    public static ConcurrentHashMap webSocketMap = new ConcurrentHashMap();

    //与某个客户端的连接会话,通过它实现定向推送(只推送给某个用户)
    private Session session;


    /**
     * 建立连接成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this);  // 添加到set中
        webSocketMap.put(session,this);    // 添加到map中
        addOnlineCount();    // 添加在线人数
        System.out.println("新人加入,当前在线人数为:"  + getOnlineCount());
    }

    /**
     * 关闭连接调用的方法
     */

    public void onClose(Session closeSession){
        webSocketMap.remove(session);
        webSocketSet.remove(this);
        subOnlineCount();
        System.out.println("有人离开,当前在线人数为:" + getOnlineCount());
    }

    /**
     *  收到客户端小心调用的方法
     */
    @OnMessage
    public void onMessage(String message,Session mysession) throws Exception{
        for (WebSocketTest item:
             webSocketSet) {
            item.sendAllMessage(message);
        }
    }

    public void sendAllMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    // 获取在线人数
    public static synchronized int getOnlineCount(){
        return onlineCount;
    }

    // 添加在线人+1
    public static synchronized void addOnlineCount(){
        onlineCount ++;
    }

    // 减少在线人-1
    public static synchronized void subOnlineCount(){
        onlineCount --;
    }
}

运行结果:

同时打开两个浏览器就可以看到结果了这里救不放图片了哈哈

本文参考博文:https://www.cnblogs.com/xdp-gacl/p/5193279.html

 

    

你可能感兴趣的:(Java的WebSocket实现)