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
posted @ 2022-08-04 16:59  诡道也  阅读(51)  评论(0编辑  收藏  举报