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文库 的其他资料.