聊天是我们人与人交流最直接的方式,互联网的加入使我们交流更加便捷。我们手机上的微信、QQ是我们手机必不可少的应用软件。那么,我们是否可以做一款聊天应用呢?

创新互联主要从事网站设计制作、网站建设、网页设计、企业做网站、公司建网站等业务。立足成都服务正定,10余年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18982081108
之前我自己闲着没事,研究过一些技术,做了一款即时通讯应用,下面我将选取几幅具有代表性的图片供大家参考。
以上是这款应用的主要页面,功能可能相对简陋点,不过基本的功能已经实现了,下面我将给出核心代码,全部源码地址在文末。
前台主要核心逻辑:
这里我只列举了js核心代码,查看完整代码可以去文末。
- function sock() {
 - return io.connect("http://localhost:3003"); // http环境下
 - }
 - // 心跳机制
 - document.addEventListener('visibilitychange', function () {
 - if (document.visibilityState == 'hidden') {
 - //记录页面隐藏时间
 - sock()
 - console.log('隐藏了')
 - }
 - })
 - setInterval(() => {
 - sock()
 - }, 10000);
 - var socket = sock()
 - var re = document.querySelector("#re");
 - var register1 = document.querySelector(".register");
 - var init = document.querySelector(".init");
 - var passr = document.querySelector("#passr");
 - var passl = document.querySelector("#passl");
 - var login1 = document.querySelector(".login");
 - var register_b = document.querySelector("#register_b");
 - var lo = document.querySelector("#lo");
 - var chat = document.querySelector("#chat");
 - var login_b = document.querySelector("#login_b");
 - var myMes = "";
 - var vf = "";
 - var na = "";
 - var p = "";
 - var we = "";
 - var div = "";
 - var v = "";
 - var q = 0;
 - var regCn = /[@:]/im;
 - var pattern = /^[\u4E00-\u9FA5]{1,5}$/;
 - // 同意
 - document.querySelector('.yes').onclick=function () {
 - document.querySelector('.dark').style.display='none'
 - }
 - document.querySelector('.ys').onclick = function () {
 - document.querySelector('.dark').style.display = 'block'
 - }
 - // 初始页面注册
 - document.querySelector("#reg").onclick = function () {
 - register1.style.display = "block";
 - init.style.display = "none";
 - document.querySelector(".bg").style.display = "none";
 - }
 - // 初始页面登录
 - document.querySelector("#log").onclick = function () {
 - login1.style.display = "block";
 - init.style.display = "none";
 - document.querySelector(".bg").style.display = "none";
 - }
 - // 登录按钮
 - login_b.onclick = function () {
 - login();
 - }
 - // 注册按钮
 - register_b.onclick = function () {
 - register();
 - }
 - //发送
 - document.getElementById("btn").onclick = function () {
 - send();
 - };
 - // 内容填充
 - document.getElementById("text").onkeyup = function () {
 - if (document.getElementById("text").value.length != 0) {
 - document.getElementById("btn").style.cssText = "background:#98E165;color:#fff;"
 - } else {
 - document.getElementById("btn").style.cssText = "background: #DDDEE2;color:#fff"
 - }
 - }
 - document.querySelector("#text").onclick = function () {
 - document.querySelector('#text').scrollIntoView(false);
 - }
 - // 传名
 - var users2 = "";
 - socket.on('users', function (users) {
 - users2 = users;
 - // console.log(users2);
 - });
 - // 传密码
 - var pass2 = ""
 - socket.on('pass', function (val) {
 - pass2 = val;
 - // console.log(pass2)
 - });
 - // 统计在线人数
 - var arrh = []
 - socket.on('dataval', function (val) {
 - vf = val;
 - console.log(vf);
 - for (let i = 0; i < vf.length; i++) {
 - // uu++
 - arrh.push(vf[i])
 - console.log(arrh)
 - }
 - var rf = [...new Set(arrh)]
 - console.log(rf)
 - rf = vf
 - for (let j = 0; j < rf.length; j++) {
 - var li = document.createElement("li");
 - li.classList.add("active");
 - li.innerText = rf[j]
 - console.log(rf[j])
 - socket.emit("time", rf[j]);
 - document.querySelector(".fix").appendChild(li);
 - }
 - });
 - socket.on('join', function (val) {
 - document.querySelector(".fix").innerHTML = ''
 - })
 - socket.on('disconnect', function (val) {
 - console.log('离开了')
 - document.querySelector(".fix").innerHTML = ''
 - })
 - // 生成数组
 - var ar = "";
 - socket.on('array', function (val) {
 - ar = val;
 - // console.log(ar);
 - });
 - // 封装注册
 - function register() {
 - if (re.value.length == 0) {
 - sweetAlert("请输入用户名!");
 - return false;
 - } else if (regCn.test(re.value)) {
 - sweetAlert("格式错误,不能够用和:符号取名,请重新输入!");
 - return false;
 - } else if (pattern.test(re.value)) {
 - sweetAlert("不能使用中文字符哦!");
 - return false;
 - } else if (!(re.value.length == 0 && regCn.test(re.value))) {
 - if (users2.indexOf(re.value) != -1) {
 - sweetAlert("已经注册啦,换一个用户名吧!");
 - } else {
 - names(re.value.trim());
 - pass(passr.value.trim());
 - sweetAlert("注册成功,您的用户名:" + re.value.trim());
 - document.querySelector(".swal-button").onclick = function () {
 - window.location.reload();
 - }
 - }
 - }
 - }
 - //移动端使用touchend
 - var event = navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i) ? 'touchend' : 'click';
 - // 选择器
 - var Q = function (id) {
 - return document.getElementById(id)
 - };
 - //右
 - var _right = new mSlider({
 - dom: ".layer-right",
 - direction: "right"
 - });
 - Q("btnRight").addEventListener(event, function (e) {
 - _right.open();
 - })
 - // 封装登录
 - function login() {
 - if (lo.value.length == 0) {
 - sweetAlert("请输入用户名!");
 - return false;
 - } else if (regCn.test(lo.value)) {
 - sweetAlert("格式错误,不能够用和:符号取名,请重新输入!");
 - return false;
 - } else if (pattern.test(lo.value)) {
 - sweetAlert("不能使用中文字符哦!");
 - return false;
 - } else if (!(lo.value.length == 0 && regCn.test(lo.value))) {
 - if (users2.indexOf(lo.value) != -1) {
 - for (var i = 0; i < users2.length; i++) {
 - if (users2[i] === lo.value && pass2[i] === passl.value) {
 - if (ar.indexOf(lo.value) == -1) {
 - sweetAlert("恭喜您,登录成功!");
 - socket.emit('setName', lo.value.trim());
 - names1(lo.value.trim());
 - login1.style.display = "none";
 - document.querySelector(".bg").style.display = "none";
 - document.querySelector(".cd span").style.display = "none";
 - document.querySelector(".title img").style.display = "block";
 - document.querySelector(".fix").style.display = "block";
 - document.querySelector(".title").style.display = "block";
 - _right.open();
 - document.querySelector(".swal-button").onclick = function () {
 - document.getElementById("text").focus();
 - document.querySelector(".fix").addEventListener('click', function (e) {
 - if (e.target.nodeName === "LI" && e.target.innerText != document.title) {
 - _right.close();
 - document.querySelector(".chat_b").style.display = "block";
 - document.querySelector(".box").style.display = "block";
 - document.querySelector(".tit").innerText = e.target.innerText;
 - document.querySelector(".ys").style.display="none";
 - document.querySelector("#text").focus();
 - onOff = true;
 - } else {
 - sweetAlert("不能跟自己聊天哦~");
 - }
 - })
 - }
 - } else {
 - sweetAlert("不能重复登录哦!");
 - return
 - }
 - }
 - if (users2[i] === lo.value && pass2[i] != passl.value) {
 - sweetAlert("密码错误!");
 - return;
 - }
 - }
 - } else {
 - sweetAlert("请先注册哦!");
 - login1.style.display = "none";
 - register1.style.display = "block";
 - }
 - }
 - }
 - // 传名
 - function names(value) {
 - this.name = value;
 - socket.emit("reg", name);
 - }
 - function names1(value) {
 - this.name1 = value;
 - socket.emit("join", name1);
 - document.title = name1
 - }
 - // 传密码
 - function pass(value) {
 - socket.emit("pass", value);
 - }
 - socket.on("join", function (user) {
 - this.na = user;
 - })
 - socket.on("reg", function (user) {
 - this.na1 = user;
 - })
 - // 私发消息
 - socket.on('message1', function (data) {
 - var p1 = document.createElement("div");
 - var s1 = document.createElement("p");
 - var s2 = document.createElement("p");
 - var div1 = document.createElement("div");
 - var em = document.createElement("em");
 - var ads = document.createElement("audio");
 - ads.src = "https://www.maomin.club/data/res.mp3";
 - ads.className = "ads";
 - s1.className = "chatlist";
 - s2.className = "chatlist1";
 - em.className = "zwasked1";
 - div1.className = "divbox";
 - s1.innerText = data.from;
 - s2.innerText = data.msg;
 - s1.appendChild(em);
 - p1.appendChild(s1);
 - p1.appendChild(s2);
 - chat.appendChild(ads);
 - ads.play();
 - div1.appendChild(p1);
 - chat.appendChild(div1);
 - chat.scrollTop = chat.scrollHeight;
 - });
 - // 私聊发送
 - function send() {
 - if (document.getElementById("text").value != "") {
 - socket.emit('sayTo', {
 - from: lo.value,
 - to: document.querySelector(".tit").innerText,
 - msg: document.querySelector("#text").value,
 - })
 - var p1 = document.createElement("div");
 - var s1 = document.createElement("p");
 - var s2 = document.createElement("p");
 - var em = document.createElement("em");
 - var div1 = document.createElement("div");
 - var ads = document.createElement("audio");
 - p1.style.cssText = "float:right;";
 - s2.style.cssText = "color:#333;"
 - ads.src = "https://www.maomin.club/data/s.wav";
 - ads.className = "ads";
 - div1.className = "divbox";
 - s1.className = "chatlist";
 - s1.style.cssText = "color:#333 !important;float:right; !important";
 - s2.className = "chatlist2";
 - em.className = "zwasked";
 - s1.innerText = lo.value;
 - s2.innerText = document.querySelector("#text").value;
 - s1.appendChild(em);
 - p1.appendChild(s1);
 - p1.appendChild(s2);
 - chat.appendChild(ads);
 - ads.play();
 - div1.appendChild(p1);
 - chat.appendChild(div1);
 - chat.scrollTop = chat.scrollHeight;
 - } else {
 - sweetAlert('请输入内容!');
 - }
 - chat.scrollTop = chat.scrollHeight;
 - document.querySelector("#text").value = "";
 - document.querySelector("#text").focus();
 - }
 
后台主要核心逻辑:
我这里只列举了http环境的,完整代码中有https环境的。
- var http=require("http");
 - var fs=require("fs");
 - var express = require('express');
 - var ws=require("socket.io");
 - var path=require("path");
 - var _ = require('underscore');
 - var usocket = [];
 - var usocket1 = [];
 - var pass=[];
 - var data=[];
 - var hashName = {};
 - var onlineCount = 0;
 - var app = express();
 - // 静态文件识别
 - app.use(express.static(path.join(__dirname, './public')));
 - var server=http.createServer(function (req,res) {
 - var filename = req.url.split('/')[req.url.split('/').length-1];
 - var suffix = req.url.split('.')[req.url.split('.').length-1];
 - if(req.url==='/'){
 - res.writeHead(200, {'Content-Type': 'text/html'});
 - var html = fs.readFileSync("./public/index.html");
 - res.end(html)
 - }else if(suffix==='css'){
 - res.writeHead(200, {'Content-Type': 'text/css'});
 - res.end(get_file_content(path.join(__dirname, 'public', 'css', filename)));
 - }else if(suffix==='js') {
 - res.writeHead(200, {'Content-Type': 'text/javascript'});
 - res.end(get_file_content(path.join(__dirname, 'public', 'js', filename)));
 - }else if (suffix in ['gif', 'jpeg', 'jpg', 'png']) {
 - res.writeHead(200, {
 - 'Content-Type': 'image/' + suffix
 - });
 - res.end(get_file_content(path.join(__dirname, 'public', 'images', filename)));
 - }
 - });
 - function get_file_content(filepath) {
 - return fs.readFileSync(filepath);
 - }
 - // 获取在线
 - function broadcast() {
 - io.sockets.emit("dataval", hashName);
 - }
 - //提供私有socket
 - function privateSocket(toId) {
 - return (_.findWhere(io.sockets.sockets, {
 - id: toId
 - }));
 - }
 - // 封装删除
 - function removeByValue(arr, val) {
 - for (var i = 0; i < arr.length; i++) {
 - if (arr[i] == val) {
 - arr.splice(i, 1);
 - break;
 - }
 - }
 - }
 - // 连接socket
 - var io=ws(server);
 - io.on("connection",function(socket){
 - // 写入成功后读取测试
 - fs.readFile('./user.xls', 'utf-8', function (err, data) {
 - if(data!=null){
 - var value = data.split('\n');
 - io.sockets.emit("users", value);
 - }
 - });
 - // 写入成功后读取测试
 - fs.readFile('./password.xls', 'utf-8', function (err,data) {
 - if(data!=null){
 - var pass1=data.split('\n');
 - io.sockets.emit("pass", pass1);
 - }
 - });
 - broadcast();
 - // 生成名字
 - socket.on('setName', function (data) {
 - var name = data;
 - hashName[name] = socket.id;
 - // console.log(hashName[name]);
 - broadcast();
 - });
 - // 私聊发送
 - socket.on('sayTo', function (data) {
 - var toName = data.to;
 - var toId;
 - console.log(toName);
 - if (toId = hashName[toName]) {
 - privateSocket(toId).emit('message1', data);
 - }
 - });
 - // 离开
 - socket.on('disconnect', function (name) {
 - name=this.i2;
 - io.emit("disconnect", name);
 - removeByValue(data, name);
 - io.sockets.emit("dataval", data);
 - })
 - // 在线
 - socket.on('time', function (val) {
 - // console.log(val);
 - })
 - // 注册
 - socket.on("reg", function (name) {
 - usocket[name] = socket;
 - this.i1=name;
 - io.emit("reg", name);
 - var myname =this.i1+"\n";
 - fs.writeFile('./user.xls', myname, {
 - 'flag': 'a'
 - }, function (err) {
 - if (err) {
 - throw err;
 - }
 - // 写入成功后读取测试
 - fs.readFile('./user.xls', 'utf-8', function (err,data) {
 - if (err) {
 - throw err;
 - }
 - });
 - });
 - })
 - // 加入
 - io.emit('connected', ++onlineCount);
 - // console.log(data);
 - io.sockets.emit("array", data);
 - socket.on("join", function (name) {
 - usocket1[name] = socket;
 - this.i2 = name;
 - io.emit("join", name);
 - data.push(name);
 - io.sockets.emit("dataval", data);
 - })
 - // 密码
 - socket.on("pass",function(val){
 - pass[val]=socket;
 - this.i2=val;
 - io.emit("pass", val);
 - var password=this.i2+"\n";
 - fs.writeFile('./password.xls', password, {
 - 'flag': 'a'
 - }, function (err) {
 - if (err) {
 - throw err;
 - }
 - });
 - })
 - });
 - server.listen(3003);
 - console.log("服务器运行中");
 
这个项目是之前写的,欢迎大家进行指正。大家可以复制下面的源码地址,拉取下来就可以在本地实现一个聊天服务。如果你有服务器可以把它部署在服务器上,这样你就可以有一个属于自己的聊天App了。大家可以根据源码进行学习,有不明白的可以随时问我。
https://github.com/maomincoding/chat3
Copyright © 2009-2022 www.wtcwzsj.com 青羊区广皓图文设计工作室(个体工商户) 版权所有 蜀ICP备19037934号