Java的WebSocket实现

Java的WebSocket实现

一、WebSocket的简单实现

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

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

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

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

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

1. 浏览器通过JavaScript 向服务器端发出建立WebScoket连接的请求,连接建立成功之后

2. 客户端和服务端就可以通过TCP连接传输数据因为WebSocket连接本质时TCP,所以不需要每次传输都带上重复的头部数据,所以数据传输比轮询和Comet技术小了很多 。

二、WebSocket实例
2.1 新建JavaWeb测试项目

在POM.xml中添加jar包依赖

    <dependency>
        <groupId>javax.websocket</groupId>
        <artifactId>javax.websocket-api</artifactId>
        <version>1.1</version>
        <scope>provided</scope>
    </dependency>

客户端(Web)代码HTML部分

1.HTML部分

<button id="connBtn">连接</button>
<input type="text" id="msg">
<button id="sendBtn" onclick="send()">发送</button>
<button id="closeBtn"  onclick="closeWebsocket()">关闭</button>
<div id="message">
</div>

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<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>();
//若要实现服务端与指定客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
public static ConcurrentHashMap<Session, Object> webSocketMap = new ConcurrentHashMap<Session, Object>();

//与某个客户端的连接会话,通过它实现定向推送(只推送给某个用户)
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 --;
}

也可以看看 GoEasy文库 的其他资料.

发表评论

邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据