webrtc scoket 聊天
let webObj = null;//全局WebSocket对象
let lockReconnect = false; // 网络断开重连
let wsCreateHandler = null; // 创建连接
let username = null; // 当前登录人姓名
let userId = null; //当亲登录人id
let toName = null; //消息接收人姓名
let toId = null;//消息接收人id
$(function() {
$(".bg_change_size").remove();
// 在ajax请求开始前将请求设为同步请求:$.ajaxSettings.async = false。
// 在ajax请求结束后不要忘了将请求设为异步请求,否则其他的ajax请求也都变成了同步请求 $.ajaxSettings.async = true。
$.ajax({
async: false,
type: 'GET',
url: "/index/getUsername",
success: function(res) {
if (!res.userId || !res.username) {
location.href = '/index/toIndex';
}
username = res.username;
userId = res.userId;
}
});
// 创建webSocket对象
createWebSocket();
// 发送消息到服务器
$(".sendMsg").on("click", function() {
sendMessage();
})
});
/**
* @title 创建连接
*/
function createWebSocket() {
try {
// 获取访问路径,带有端口号:ws://localhost/webSocket/001
let host = window.location.host;
// 创建WebSocket连接对象
webObj = new WebSocket(`ws://${host}/webSocket/${userId}`);
// 加载组件
initWsEventHandle();
} catch (e) {
ml.msgBox("连接出错,正在尝试重新连接,请稍等。。。");
// 尝试重新连接服务器
reconnect();
}
}
/**
* @title 初始化组件
*/
function initWsEventHandle() {
try {
// 建立连接
webObj.onOpen = function(evt) {
onWsOpen(evt);
// 建立连接之后,开始传输心跳包
heartCheck.start();
};
// 传送消息
webObj.onmessage = function(evt) {
// 发送消息
onWsMessage(evt);
// 接收消息后 也需要心跳包的传送
heartCheck.start();
};
// 关闭连接
webObj.onclose = function(evt) {
// 关闭连接,可能是异常关闭,需要重新连接
onWsClose(evt);
// 尝试重新连接
reconnect();
};
// 连接出错
webObj.onerror = function(evt) {
// 连接出错
onWsError(evt);
// 尝试重新连接
reconnect();
}
} catch (e) {
if (e) {
conlog("catch", e);
}
ml.msgBox("初始化组件失败,正在重试,请稍后。。。");
// 尝试重新创建连接
reconnect();
}
}
/**
* @title 建立连接
*/
function onWsOpen(e) {
if (e.data) {
conlog("onWsOpen", e.data);
}
ml.msgBox("建立连接成功。。。");
}
/**
* @title 传送消息内容
*/
function onWsMessage(e) {
if (e.data) {
conlog("onWsMessage", e.data);
}
let jsonStr = e.data;
//接收到服务器推送的消息后触发事件
message(e);
}
/**
* @title 关闭连接
*/
function onWsClose(e) {
if (e.data) {
conlog("onWsClose", e.data);
}
ml.msgBox("连接关闭,尝试重新连接服务器,请稍侯。。。");
closeFun(e);
}
/**
* @title 连接出错
*/
function onWsError(e) {
ml.msgBox("连接出错,正在尝试重新连接服务器,请稍侯。。。" + e.data);
}
/**
* @title 输出数据到控制台
*/
function conlog(msg) {
conlog('', msg);
}
/**
* @title 输出数据到控制台
*/
function conlog(title, msg) {
let content = msg;
if (title) {
content = `${title}:${msg}`;
}
console.log(`${content}`);
}
/**
* @title 异常处理
* @Desc 处理可以检测到的异常,并尝试重新连接
*/
function reconnect() {
if (lockReconnect) {
return;
}
conlog("reconnect");
ml.msgBox("正在尝试重新连接,请稍侯。。。");
lockReconnect = true;
// 没链接上会一直连接,设置延迟,避免过多请求
wsCreateHandler && clearTimeout(wsCreateHandler);
wsCreateHandler = setTimeout(function() {
ml.msgBox("正在重新连接。。。");
createWebSocket();
lockReconnect = false;
ml.msgBox("重连完成。。。");
}, 1000);
}
/**
* @title 心跳检测
* @Desc 网络中断,系统无法捕获,需要心跳检测实现重新连接
*/
var heartCheck = {
// 在15s内若没收到服务端消息,则认为连接断开,需要重新连接
timeout: 15000, // 心跳检测触发时间
timeoutObj: null,
serverTimeoutObj: null,
// 重新连接
reset: function() {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
this.start();
},
// 开启定时器
start: function() {
let self = this;
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(function() {
ml.msgBox("发送ping到后台服务。。。");
try {
webObj.send("PING");
} catch (e) {
ml.msgBox("发送ping异常。。。");
}
//内嵌定时器
self.serverTimeoutObj = setTimeout(function() {
// 若onclose方法会执行reconnect方法,我们只需执行close()就行,
// 若直接执行reconnect会触发onclose导致重连两次
ml.msgBox("没有收到后台数据,关闭连接。。。");
webObj.close();
//reconnect();
}, self.timeout);
}, this.timeout);
}
};
/**
* @title 组织并解析数据
*/
function message(e) {
//获取服务端推送过来的消息
let message = e.data;
// 将message转为JSON对象
let res = JSON.parse(message);
// 是否为系统消息
if (res.systemMsgFlag) {
let allNames = res.message;
//1. 好友列表展示 2. 系统推广
let userListStr = "";
let broadcastListStr = "";
let imgUrl = "../imgs/chatIc.png";
for (let user of allNames) {
if (user.userId != userId) {
userListStr += `<li class="friend-li" οnclick='chatWith("${user.userId}","${user.username}",this);'><img src="${imgUrl}" class='friendList-img'><span>${user.username}</span></li>`;
broadcastListStr += `<li style='color:#9d9d9d;font-family:宋体;'>
<span style='font-size:5px;color:black;'>${user.dateStr}</span><br/>
好友<span>${user.username}</span>上线了!
</li>`;
}
}
$(".friend-list").html(userListStr);
$(".sys-msg").html(broadcastListStr);
} else {
// 不是系统消息
let msgText = res.message;
let msg = `<li class='friend-msg-li'><img src='${imgUrl}' class='img'/><span class='friend-span'>${msgText}</span></li>`;
if (toId === res.fromId) {
$(".chat-msg").append(msg);
}
let chatData = sessionStorage.getItem(res.fromId);
if (chatData) {
msg = chatData + msg;
}
sessionStorage.setItem(res.fromId, msg);
$(".chat-main")[0].scrollTop = $(".chat-main")[0].scrollHeight;
}
}
// 关闭连接
function closeFun(e) {
let tips = `<span style='font-size:5px;color:black;'>${new Date()}</span><br/>`;
$(".sys-msg").html(`${tips}用户:${username}<span style="float:right;color:red;">离开了</span>`);
}
// 选择好友
function chatWith(id, name, obj) {
toId = id;
toName = name;
$(".edit-msg").attr("disabled", false);
$(".div-btn").show();
$(".chat-msg").show();
$(obj).addClass("selected-li").siblings().removeClass("selected-li");
let chatNow = `正在和<span style="color: #db41ca;">${name}</span>聊天`;
$(".div-main-title").html(chatNow);
$(".chat-msg").html("");
var chatData = sessionStorage.getItem(toId);
if (chatData) {
//渲染聊天数据到聊天区
$(".chat-msg").html(chatData);
}
$(".chat-main")[0].scrollTop = $(".chat-main")[0].scrollHeight;
}
/**
* @title 组织和发送消息到服务器
*/
function sendMessage() {
// 发送消息
if (!toId || !toName) {
ml.tips("sendMsg", "请选择好友...");
return;
}
let msg = $(".edit-msg").val();
if (!msg) {
let webObj = null;//全局WebSocket对象
let lockReconnect = false; // 网络断开重连
let wsCreateHandler = null; // 创建连接
let username = null; // 当前登录人姓名
let userId = null; //当亲登录人id
let toName = null; //消息接收人姓名
let toId = null;//消息接收人id
$(function() {
$(".bg_change_size").remove();
// 在ajax请求开始前将请求设为同步请求:$.ajaxSettings.async = false。
// 在ajax请求结束后不要忘了将请求设为异步请求,否则其他的ajax请求也都变成了同步请求 $.ajaxSettings.async = true。
$.ajax({
async: false,
type: 'GET',
url: "/index/getUsername",
success: function(res) {
if (!res.userId || !res.username) {
location.href = '/index/toIndex';
}
username = res.username;
userId = res.userId;
}
});
// 创建webSocket对象
createWebSocket();
// 发送消息到服务器
$(".sendMsg").on("click", function() {
sendMessage();
})
});
/**
* @title 创建连接
*/
function createWebSocket() {
try {
// 获取访问路径,带有端口号:ws://localhost/webSocket/001
let host = window.location.host;
// 创建WebSocket连接对象
webObj = new WebSocket(`ws://${host}/webSocket/${userId}`);
// 加载组件
initWsEventHandle();
} catch (e) {
ml.msgBox("连接出错,正在尝试重新连接,请稍等。。。");
// 尝试重新连接服务器
reconnect();
}
}
/**
* @title 初始化组件
*/
function initWsEventHandle() {
try {
// 建立连接
webObj.onOpen = function(evt) {
onWsOpen(evt);
// 建立连接之后,开始传输心跳包
heartCheck.start();
};
// 传送消息
webObj.onmessage = function(evt) {
// 发送消息
onWsMessage(evt);
// 接收消息后 也需要心跳包的传送
heartCheck.start();
};
// 关闭连接
webObj.onclose = function(evt) {
// 关闭连接,可能是异常关闭,需要重新连接
onWsClose(evt);
// 尝试重新连接
reconnect();
};
// 连接出错
webObj.onerror = function(evt) {
// 连接出错
onWsError(evt);
// 尝试重新连接
reconnect();
}
} catch (e) {
if (e) {
conlog("catch", e);
}
ml.msgBox("初始化组件失败,正在重试,请稍后。。。");
// 尝试重新创建连接
reconnect();
}
}
/**
* @title 建立连接
*/
function onWsOpen(e) {
if (e.data) {
conlog("onWsOpen", e.data);
}
ml.msgBox("建立连接成功。。。");
}
/**
* @title 传送消息内容
*/
function onWsMessage(e) {
if (e.data) {
conlog("onWsMessage", e.data);
}
let jsonStr = e.data;
//接收到服务器推送的消息后触发事件
message(e);
}
/**
* @title 关闭连接
*/
function onWsClose(e) {
if (e.data) {
conlog("onWsClose", e.data);
}
ml.msgBox("连接关闭,尝试重新连接服务器,请稍侯。。。");
closeFun(e);
}
/**
* @title 连接出错
*/
function onWsError(e) {
ml.msgBox("连接出错,正在尝试重新连接服务器,请稍侯。。。" + e.data);
}
/**
* @title 输出数据到控制台
*/
function conlog(msg) {
conlog('', msg);
}
/**
* @title 输出数据到控制台
*/
function conlog(title, msg) {
let content = msg;
if (title) {
content = `${title}:${msg}`;
}
console.log(`${content}`);
}
/**
* @title 异常处理
* @Desc 处理可以检测到的异常,并尝试重新连接
*/
function reconnect() {
if (lockReconnect) {
return;
}
conlog("reconnect");
ml.msgBox("正在尝试重新连接,请稍侯。。。");
lockReconnect = true;
// 没链接上会一直连接,设置延迟,避免过多请求
wsCreateHandler && clearTimeout(wsCreateHandler);
wsCreateHandler = setTimeout(function() {
ml.msgBox("正在重新连接。。。");
createWebSocket();
lockReconnect = false;
ml.msgBox("重连完成。。。");
}, 1000);
}
/**
* @title 心跳检测
* @Desc 网络中断,系统无法捕获,需要心跳检测实现重新连接
*/
var heartCheck = {
// 在15s内若没收到服务端消息,则认为连接断开,需要重新连接
timeout: 15000, // 心跳检测触发时间
timeoutObj: null,
serverTimeoutObj: null,
// 重新连接
reset: function() {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
this.start();
},
// 开启定时器
start: function() {
let self = this;
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(function() {
ml.msgBox("发送ping到后台服务。。。");
try {
webObj.send("PING");
} catch (e) {
ml.msgBox("发送ping异常。。。");
}
//内嵌定时器
self.serverTimeoutObj = setTimeout(function() {
// 若onclose方法会执行reconnect方法,我们只需执行close()就行,
// 若直接执行reconnect会触发onclose导致重连两次
ml.msgBox("没有收到后台数据,关闭连接。。。");
webObj.close();
//reconnect();
}, self.timeout);
}, this.timeout);
}
};
/**
* @title 组织并解析数据
*/
function message(e) {
//获取服务端推送过来的消息
let message = e.data;
// 将message转为JSON对象
let res = JSON.parse(message);
// 是否为系统消息
if (res.systemMsgFlag) {
let allNames = res.message;
//1. 好友列表展示 2. 系统推广
let userListStr = "";
let broadcastListStr = "";
let imgUrl = "../imgs/chatIc.png";
for (let user of allNames) {
if (user.userId != userId) {
userListStr += `<li class="friend-li" οnclick='chatWith("${user.userId}","${user.username}",this);'><img src="${imgUrl}" class='friendList-img'><span>${user.username}</span></li>`;
broadcastListStr += `<li style='color:#9d9d9d;font-family:宋体;'>
<span style='font-size:5px;color:black;'>${user.dateStr}</span><br/>
好友<span>${user.username}</span>上线了!
</li>`;
}
}
$(".friend-list").html(userListStr);
$(".sys-msg").html(broadcastListStr);
} else {
// 不是系统消息
let msgText = res.message;
let msg = `<li class='friend-msg-li'><img src='${imgUrl}' class='img'/><span class='friend-span'>${msgText}</span></li>`;
if (toId === res.fromId) {
$(".chat-msg").append(msg);
}
let chatData = sessionStorage.getItem(res.fromId);
if (chatData) {
msg = chatData + msg;
}
sessionStorage.setItem(res.fromId, msg);
$(".chat-main")[0].scrollTop = $(".chat-main")[0].scrollHeight;
}
}
// 关闭连接
function closeFun(e) {
let tips = `<span style='font-size:5px;color:black;'>${new Date()}</span><br/>`;
$(".sys-msg").html(`${tips}用户:${username}<span style="float:right;color:red;">离开了</span>`);
}
// 选择好友
function chatWith(id, name, obj) {
toId = id;
toName = name;
$(".edit-msg").attr("disabled", false);
$(".div-btn").show();
$(".chat-msg").show();
$(obj).addClass("selected-li").siblings().removeClass("selected-li");
let chatNow = `正在和<span style="color: #db41ca;">${name}</span>聊天`;
$(".div-main-title").html(chatNow);
$(".chat-msg").html("");
var chatData = sessionStorage.getItem(toId);
if (chatData) {
//渲染聊天数据到聊天区
$(".chat-msg").html(chatData);
}
$(".chat-main")[0].scrollTop = $(".chat-main")[0].scrollHeight;
}
/**
* @title 组织和发送消息到服务器
*/
function sendMessage() {
// 发送消息
if (!toId || !toName) {
ml.tips("sendMsg", "请选择好友...");
return;
}
let msg = $(".edit-msg").val();
if (!msg) {
ml.tips("sendMsg", "请输入内容...");
return;
}
let img = `<img src='${imgUrl}' class='myself-img'/>`;
let li = $("<li class='myself-li'></li>");
li.html(`${img}<span class='myself-span'>${msg}</span>`);
$(".chat-msg").append(li);
$(".edit-msg").val('');
$(".chat-main")[0].scrollTop = $(".chat-main")[0].scrollHeight;
let chatData = sessionStorage.getItem(toId);
let liStr = `<li class='myself-li'>${img}<span class='myself-span'>${msg}</span></li>`;
if (chatData) {
liStr = chatData + liStr;
}
let jsonMessage = {
"fromName": username, //消息发送人姓名
"fromId": userId, //消息发送人id
"toName": toName, //消息接收人姓名
"toId": toId, //消息接收人id
"message": msg //发送的消息内容
};
// 将消息存放到sessionStorage中
sessionStorage.setItem(toId, liStr);
// 发送数据给服务器(消息发送格式为JSON格式)
webObj.send(JSON.stringify(jsonMessage));
}
ml.tips("sendMsg", "请输入内容...");
return;
}
let img = `<img src='${imgUrl}' class='myself-img'/>`;
let li = $("<li class='myself-li'></li>");
li.html(`${img}<span class='myself-span'>${msg}</span>`);
$(".chat-msg").append(li);
$(".edit-msg").val('');
$(".chat-main")[0].scrollTop = $(".chat-main")[0].scrollHeight;
let chatData = sessionStorage.getItem(toId);
let liStr = `<li class='myself-li'>${img}<span class='myself-span'>${msg}</span></li>`;
if (chatData) {
liStr = chatData + liStr;
}
let jsonMessage = {
"fromName": username, //消息发送人姓名
"fromId": userId, //消息发送人id
"toName": toName, //消息接收人姓名
"toId": toId, //消息接收人id
"message": msg //发送的消息内容
};
// 将消息存放到sessionStorage中
sessionStorage.setItem(toId, liStr);
// 发送数据给服务器(消息发送格式为JSON格式)
webObj.send(JSON.stringify(jsonMessage));
}
地址:https://blog.csdn.net/qq_51076413/article/details/124644500?spm=1001.2100.3001.7377&utm_medium=distribute.pc_feed_blog_category.none-task-blog-classify_tag-6-124644500-null-null.nonecase&depth_1-utm_source=distribute.pc_feed_blog_category.none-task-blog-classify_tag-6-124644500-null-null.nonecase
加班万岁!