WebSocket,实现简单的广播功能
程序员文章站
2022-05-21 21:26:02
...
改变现在,从通讯开始
传统的前端和后端的数据交互是使用轮询方法,会占用大量资源。在如今高速发展的时代,一种能提升效率的方法或者说新技术便显得尤为重要。
websocket便是这样一种技术,有关于它的更多的一些细节,大家可以自行百度。(本博客部分代码来源自网上,向前辈们致敬)
这里看一下广播的演示结果:
不写代码,终究是纸上谈兵
(csdn不能把资源免费了!)
websocket jar包下载
这里只是展示websocket的一个小demo,并未对界面做过多要求。于是只设计了一个简单的发送消息文本框和按钮。加载页面时初始化socket,点击按钮触发socket.send(msg)方法便可。由于是多客户端广播,每一个socket在连接服务器时需要加上自己相应的id参数。(这里生成id参数方法并不推荐)
<%-- Created by IntelliJ IDEA. --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>WebSocket 客户端</title>
</head>
<body>
<div>
<div class="main">
<input name="message" id="msg" onkeydown="if (event.keyCode==13) sendMsg()"/>
<button onclick="sendMsg()">发送</button>
</div>
</div>
<script src="resource/js/jquery.js" type="text/javascript" charset="utf-8"></script>
<script src="resource/js/socket.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var uid = getRandomWithoutRepeat([1,2,3,4,5,6,7,8,9,10]);//获取当前账户的id;
var url="ws://127.0.0.1:8080/webSocketServer/"+uid[0];
var socket = getSocket(url);
bindMethod(socket);
function sendMsg() {
Log("发送:"+$("#msg").val(),"INFO");
socket.send($("#msg").val());
$("#msg").val("")
}
window.onbeforeunload = function() {
socket.close();
};
/**
* 创建随机数
* @param Min
* @param Max
* @returns {*}
* @constructor
*/
function getRandom(Min,Max){
var Range = Max - Min;
var Rand = Math.random();
return(Min + Math.round(Rand * Range));
}
/**
* 获取不重复的随机数
* @param arr
* @returns {Array}
*/
function getRandomWithoutRepeat(arr){
var temp=[]; //temp存放生成的随机数组
for (var i=0;i<arr.length;i++)
{
var num=Math.floor(Math.random()*arr.length); //生成随机数num
temp.push(arr[num]); //获取arr[num]并放入temp
arr.splice(num,1);
}
return temp;
}
</script>
</body>
</html>
可以发现上述界面部分引入了socket.js文件,这个是我自己抽象出来的一部分可供重用的方法部分,比如说打印日志和创建websocket的代码。
/**
* Created by zipple on 2017/9/28.
* 创建web socket 对象
* 定义相关方法
*/
/**
* 创建socket对象
* @param url
* @returns {WebSocket}
*/
function getSocket(url) {
if(typeof(WebSocket) == "undefined") { //此处判断支持Android
alert("您的浏览器不支持WebSocket");
}
Log("建立socket对象","OK");
return new WebSocket(url);
}
/**
* 为创建的socket对象绑定相关方法
* @param ws
* @param elements 获取信息的地方
*/
function bindMethod(ws) {
ws.onopen = function () {
Log("连接成功","OK")
};
ws.onmessage = WSonMessage;
ws.onclose = WSonClose;
ws.onerror = WSonError;
}
/**
* 获取数据
* @param event
*/
function WSonMessage(event) {
Log("获取到信息:"+event.data,"OK");
var div = "<div>"+event.data+"</div>";
$("body").prepend($(div))
}
/**
* 关闭连接
*/
function WSonClose() {
Log("连接关闭。", "ERROR");
}
/**
* 链接异常
*/
function WSonError() {
Log("WebSocket错误。", "ERROR");
}
/**
* 在控制台打印数据
* @param msg
* @param type
*/
function Log(msg,type) {
switch (type){
case 0 :
type="ERROR";
break;
case 1:
type="OK";
break;
case 2:
type="WARNING";
break;
default:
type="INFO"
}
console.log(type+":"+msg+" at "+getNowFormatDate());
}
/**
* 获取系统当前时间
* @returns {string}
*/
function getNowFormatDate() {
var currentdate="error occurred in getNoeFormatDate";
var date = new Date();
var seperator1 = "-";
var seperator2 = ":";
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate
+ " " + date.getHours() + seperator2 + date.getMinutes()
+ seperator2 + date.getSeconds();
return currentdate;
}
后台:接收连接请求,储存session,遍历对象,转发msg
为了实现用户的广播(即将某个用户发送到服务器端的信息转发至所有用户)功能,我们需要在接收到用户websocket连接请求时储存当前用户的session,用于转发数据。
因为这只是一个简单的demo入门,便不再考虑其他的相关安全操作,下线判断等等。
package webSocket;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
/**
* 多个用户之间的通讯
*/
@ServerEndpoint("/webSocketServer/{userId}")
public class WebSocketServer {
private Session session;
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
/**
* 连接建立成功调用的方法
* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(@PathParam("userId") String userId,Session session){
System.out.println("Client connected "+userId);//在这里储存用户
this.session =session;
webSocketSet.add(this);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(@PathParam("userId") String userId){
System.out.println("Connection closed");
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(@PathParam("userId") String userId,String message) throws IOException {
System.out.println("服务器接收用户"+userId+"消息: " + message);
for (WebSocketServer ws: webSocketSet){
ws.session.getBasicRemote().sendText("服务器回复:"+message);
}
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
error.printStackTrace();
}
}
好吧!
其实是写这篇博客的时候太困了!
坚持不住了,就直接把所有源码贴上来了。
没有做过多解释,请同行见谅。
你逃避的北上广,是我曾向往过的远方
上一篇: Redis发布与订阅操作