一、 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的一点经验,代码多变,方法也不尽相同。仅留作日后参考。
有错误还请大家指正。