这次给大家分享的是我自己开发的多人聊天室,利用websocket 以及服务器端使用node.js 来让用户不需要刷新浏览器就可以获得实时更新。

如下面图所示的样子。开发出类QQ群聊天室的主界面,当然UI还是有点难看。。。

使用的技术要点罗列:nodejs 安装与使用 websocket 客户端以及nodejs 服务器端的 API接口调用  js,jq 的用法  包括设置cookie date函数使用,html5 本地存储方式 local storage 的使用方法   以及表情的选择与发送这几个方面。现在跟我一起来完成它吧。

第一步,先了解下 websocket 是什么,为什么在线聊天室 需要这样的方式来进行,而传统的http模式有什么弊端。可以参考下百度百科中的websocket定义http://baike.baidu.com/link?url=UdkmadppMSP7B0LpZU1VUhCXW0kKii1oRZ8o-Pn77IHs_3KyCp70FKethp3TBNpsSuSC6fZw3hMlV7_ZZ20BZ_。当然现在如日中天的node.js已经完全封装好了websocket API的所有内容 ,当然大家可以去http://www.open-open.com/lib/view/open1402479198587.html看看websocket 是怎么定义的,websocket协议与平常http 协议有什么不一样。现在把这块内容稍微消化下,我们就可以开始动手开始实现吧。

安装node.js 。大家还是可以去看这篇http://www.open-open.com/lib/view/open1402479198587.html  ,

根据自己的操作系统,去Node.js官网下载安装即可。如果成功安装。在命令行输入node -vnpm -v应该能看到相应的版本号。

当出来以上信息时候,说明你的node.js已经安装成功了!

搭建自己的websocket 服务器。 接下来使用npm命令安装expresssocket.io

安装成功后,会在该文件夹下生成了一个名为node_modules的文件夹,里面分别是expresssocket.io相关的文件集,再这里新建个服务器的代码  server.js

就可以开始编写服务端的代码了。

server.js  最开始的代码

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);app.get('/',function(req,res){res.send('<h1>Welcome Realtime Server</h1>');
});http.listen(3000,function(){console.log('listening on *:3000');
});

这时候 你就可以运行下代码  node server.js 来开启服务了

出现该截图内容 就说明websocket服务器已成功 运行了,你也可以打开浏览器 ,输入localhost:3000来看看3000端口上运行的websocket服务器是否启动

接下来,就可以开始着手前端的准备工作(包括界面图片样式等等的) 一开始 我是抱着学习的心态 使用了http://www.oschina.net/code/snippet_230665_21329这里面的UI设计,大家也可以使用。好,我们先要运行起来,完成用户登录完 就能在后台收到信息的功能

var my_websocket = io.connect('ws://localhost:3000');//js获取当前时间var NowDateTime = getNowFormatDate();console.log(my_websocket);my_websocket.on('connect',function(){my_websocket.emit("login",tourist);my_websocket.on('login_message',function(message){//刚进聊天室时候在聊天框显示某某进入聊天室console.log(message);//每次登陆先删除右边栏所有的用户$("#userck").siblings().remove();scrollWindow()var self_content = "<span class=\"content_nowtime\">["+NowDateTime+"]</span>";self_content += "  <a class=\"content_tourist\">"+message.user_now+"</a>来到了聊天室:<br><br>";content_div.append(self_content); //在右侧观众栏添加刚登陆的游客var ParentTourist = $("#autors"); for (i in message.user_array){var SonTourist = "<a class=\"userck\">"+message.user_array[i]+"</a>";ParentTourist.append(SonTourist); }var touristCount = "所有人-共 "+message.user_count+" 人";$("#userck").text(touristCount);});

当然后台也要加上获取客户端发送消息的代码

    var userArr = new Array();var userCount = 0;
io.on('connection',function(socket)
{   console.log('a user connected');socket.on('login',function(obj) {//判断是否是新用户登录  indexOf是js 判断数组是否包含一个元素的函数 大于0表示包含 -1表示不包含 if(userArr.indexOf(obj) == '-1'){userArr.push(obj); userCount ++;      }var login_message =    {                      user_array : userArr,           user_count : userCount,         user_now   : obj}                      console.log(login_message);     //将所有用户登录的信息发给所有用户io.sockets.emit('login_message',login_message);});

还有一点主意的  客户端发送消息通知给服务器端代码时   是用

my_websocket.emit("login",tourist);
然后服务器端接收到单个客户端推送的信息时 ,他需要推送给所有在线的用户  所以需要使用
<pre name="code" class="javascript">io.sockets.emit('login_message',login_message);

这时候 客户端收到 服务器端返回的login_message值的时候  我们就要进行开发这个方法了

 my_websocket.on('message',function(msg){//在聊天框添加聊天的记录sendTime = msg.send_time;username = msg.username;tourist_message = replace_em(msg.content);console.log(msg);if(getcookie("tourist") == username){var self_content = "<div class=\"receiver\">";self_content += "<div><img src=\"arclist/online_chat_face.jpg\" style=\"width:50px;height:50px\"></div>";self_content += "<div><div class=\"right_triangle\"></div>";self_content += "<p class=\"receiver_name_r\">"+username+"</p>";self_content += "<span>"+tourist_message+"</span>";self_content += "</div></div><br>";self_content += "<div class=\"clear\"></div>";/*var self_content = "<span class=\"content_nowtime\">["+sendTime+"]</span>";self_content += "  <a class=\"content_tourist\">"+username+"</a>说:";self_content += tourist_message+"<br>";*/}else

当然大家也可以先用注释中的简单哪代码先来实现该方法  没有注释那段是使用类QQ群聊天那样的气泡模式 ,getcookie这个方法是调用了cookie的值来判断是不是本人发送的消息 ,如果是的话气泡就会在右边   如果发送成功的话 ,大家可以在服务器端看到如下的代码反馈

这样就说明传输成功了 ,当然到界面上就会有如下显示

当然完成这一步的时候。你就已经成功了一大半了,接下来就是不断调试,尝试着用虚拟机跟你对话吧,就像开头的截图一样。。。

附上源码链接 https://github.com/taweisuode/online_chat  大家可以去下载,我也会不定期去更新完善里面的内容。

好了。当大家把所有登录。发送消息。退出时候的消息都能够实时发送,并且右侧状态栏也能够实时显示在线人数以及在线人姓名时。我们就要对其进行完善以及优化了

可以添加以下内容   1. 按enter键发送消息;2.将一些用户信息存储在local  storage 中;然后根据失效时间 是否删除所有的local Storage数据 ,这样可以判断你的上次登录时间;

3.当聊天内容多余div的高度时,我们需要使用滚动轴,源代码有简单使聊天框都在滚动轴最下方的代码;4.可以使用表情来发送;5.可以使用类QQ群聊天的气泡对话模式;

当然这些都放在源码中 。大家也可以去https://github.com/taweisuode/online_chat  下载。

大概就说这么多了,这是小弟我第一次发表博客,不足之处希望大家能够批评指正。如有不懂的问题。可以随时请教。我的联系方式1064480036@qq.com

以下贴出我的客户端 以及服务器端的源码。

客户端的代码

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>socket</title>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="chat_server/node_modules/socket.io-client/socket.io.js"></script>
<script type="text/javascript" src="jquery.qqFace.js"></script>
<link type="text/css" href="css/main.css" rel="stylesheet" />
</head><body>
<div style="text-align:center; margin-left:auto; margin-right:auto; "><b>鹏哥聊天室</b></div>
<div id="cc"><div id="content"><a href="#" id="clearAll" οnclick="clearAll()" style="float:right">清空记录</a></div><div id="autors"><a href="javascript:;" οnclick="ac('all',this)" class="userck" id="userck">所有人 -共 0 人</a></div>
</div>
<div id="cb">
<span class="an1">请交流吧:</span>
<input type="text" id="sending"  value="" style="width: 500px; height: 30px;"/>
<span class="emotion"><img src="arclist/start_face.jpg" style="width:25px;height:25px;margin-bottom: -6px; margin-right: 5px;"/></span>
<input type="button" value="发送" id="send_message"  style="width: 100px; height: 38px;">
<input type="hidden" value="" id="cookieName" />
</div>
<script>//获取聊天框对象   用content_div.append(self_content);就能发布信息 var content_div = $("#content"); //设置localStorage对象var storage = window.localStorage;//调用js 时间对象var nowDate  = new Date();  //设置cookie方法function setcookie(name,value){  var Days = 1;  var exp  = new Date();  exp.setTime(exp.getTime() + Days*24*60*60*1000);  document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();  }  //获取cookie方法function getcookie(name){  var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));  if(arr != null){  return (arr[2]);  }else{  return "";  }  }  //删除cookie方法function delcookie(name){  var exp = new Date();  exp.setTime(exp.getTime() - 1);  var cval=getCookie(name);  if(cval!=null) document.cookie= name + "="+cval+";expires="+exp.toGMTString();  }  //js获取当前时间方法(可传时间戳参数)function getNowFormatDate(timestamp = null) {if(timestamp){var date = new Date(timestamp);}else{var date = new Date();}var seperator1 = "-";var seperator2 = ":";var month = date.getMonth() + 1;var strDate = date.getDate();var strHours = date.getHours();var strMinutes = date.getMinutes();var strSeconds = date.getSeconds();if (month >= 1 && month <= 9) {month = "0" + month;}if (strDate >= 0 && strDate <= 9) {strDate = "0" + strDate;}if (strHours >= 0 && strHours <= 9) {strHours = "0" + strHours;}if (strMinutes >= 0 && strMinutes <= 9) {strMinutes = "0" + strMinutes;}if (strSeconds >= 0 && strSeconds <= 9) {strSeconds = "0" + strSeconds;}var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate+ " " + strHours + seperator2 + strMinutes+ seperator2 + strSeconds;return currentdate;}$(function(){if(!getcookie("tourist")){var tourist=prompt("请输入您的名字","");if(tourist)//如果返回的有内容{setcookie("tourist",tourist);$("#socketName").val(tourist);alert("欢迎您:"+ tourist);}}else{var tourist = getcookie("tourist");alert("欢迎您回来:"+ tourist);}//在登陆时候记录下登陆时间-记录到localstorage中,然后根据失效时间 是否删除所有的localhostStorage数据if(storage.getItem("nowTime")){if(nowDate.getTime() - storage.getItem("nowTime") <= (1000*60*60*24)){var ever_timestamp =  parseInt(storage.getItem("nowTime")); //这块要用parseInt函数解析一个字符串,并返回一个整数//调用js 根据时间戳返回标准时间方法var format_time = getNowFormatDate(ever_timestamp);//var format_time = formatDate(storage.getItem("nowTime"));var self_content = "  <a class=\"content_tourist\">"+getcookie("tourist")+"</a>曾来到了聊天室,时间为";self_content += "<span class=\"content_nowtime\">["+format_time+"]</span><br>";content_div.append(self_content); }else{storage.removeItem(getcookie("tourist")+"--message");}}//storage.setItem("nowTime",nowDate.getTime());//alert(nowDate.getTime());//websocket = new WebSocket("ws://localhost:3000");var my_websocket = io.connect('ws://localhost:3000');//js获取当前时间var NowDateTime = getNowFormatDate();console.log(my_websocket);my_websocket.on('connect',function(){my_websocket.emit("login",tourist);my_websocket.on('login_message',function(message){//刚进聊天室时候在聊天框显示某某进入聊天室console.log(message);//每次登陆先删除右边栏所有的用户$("#userck").siblings().remove();scrollWindow()var self_content = "<span class=\"content_nowtime\">["+NowDateTime+"]</span>";self_content += "  <a class=\"content_tourist\">"+message.user_now+"</a>来到了聊天室:<br><br>";content_div.append(self_content); //在右侧观众栏添加刚登陆的游客var ParentTourist = $("#autors"); for (i in message.user_array){var SonTourist = "<a class=\"userck\">"+message.user_array[i]+"</a>";ParentTourist.append(SonTourist); }var touristCount = "所有人-共 "+message.user_count+" 人";$("#userck").text(touristCount);});my_websocket.on('message',function(msg){//在聊天框添加聊天的记录sendTime = msg.send_time;username = msg.username;tourist_message = replace_em(msg.content);console.log(msg);if(getcookie("tourist") == username){var self_content = "<div class=\"receiver\">";self_content += "<div><img src=\"arclist/online_chat_face.jpg\" style=\"width:50px;height:50px\"></div>";self_content += "<div><div class=\"right_triangle\"></div>";self_content += "<p class=\"receiver_name_r\">"+username+"</p>";self_content += "<span>"+tourist_message+"</span>";self_content += "</div></div><br>";self_content += "<div class=\"clear\"></div>";/*var self_content = "<span class=\"content_nowtime\">["+sendTime+"]</span>";self_content += "  <a class=\"content_tourist\">"+username+"</a>说:";self_content += tourist_message+"<br>";*/ }else{var self_content = "<div class=\"sender\">";self_content += "<div><img src=\"arclist/online_chat_face.jpg\" style=\"width:50px;height:50px\"></div>";self_content += "<div><div class=\"left_triangle\"></div>";self_content += "<p class=\"receiver_name_l\">"+username+"</p>";self_content += "<span>"+tourist_message+"</span>";self_content += "</div></div>";self_content += "<div class=\"clear\"></div>";/*var self_content = "<span class=\"content_nowtime\">["+sendTime+"]</span>";self_content += "  <a class=\"content_tourist\">"+username+"</a>说:";self_content += tourist_message+"<br>";*/ }content_div.append(self_content); scrollWindow()//并加聊天记录添加到localStorage中,用来在用户再次登陆时候体现上次登录的内容var storageKey = getcookie("tourist")+"--message";//storage.setItem(storageKey,message);});//关闭窗口后触发用户退出功能 window.onunload = onunload_handler;function onunload_handler(){my_websocket.emit("logout",tourist);}my_websocket.on('logout_message',function(message){$("#userck").siblings().remove();var self_content = "<span class=\"content_nowtime\">["+NowDateTime+"]</span>";self_content += "  <a class=\"content_tourist\">"+message.user_now+"</a>退出了聊天室:<br>";content_div.append(self_content); //在右侧观众栏添加刚登陆的游客var ParentTourist = $("#autors"); for (i in message.user_array){var SonTourist = "<a class=\"userck\">"+message.user_array[i]+"</a>";ParentTourist.append(SonTourist); }var touristCount = "所有人-共 "+message.user_count+" 人";$("#userck").text(touristCount);});//赋予输入框enter按键发送消息的功能$(document).keypress(function(e){var self_message = $("#sending").val();if(e.keyCode == 13 && self_message){var content_div = $("#content"); var NowDateTime = getNowFormatDate();if(self_message){var data = {username : tourist,content  : self_message,send_time: NowDateTime}my_websocket.emit("message",data);$("#sending").val("") ;}else{alert("不能发送空消息");}}});$("#sending").keypress(function(e){var tourist = getcookie("tourist");if(e.keyCode == 13){var content_div = $("#content"); var self_message = $("#sending").val();var NowDateTime = getNowFormatDate();if(self_message){var data = {username : tourist,content  : self_message,send_time: NowDateTime}my_websocket.emit("message",data);$("#sending").val("") ;}else{alert("不能发送空消息");}}});//发送按钮点击发送功能$("#send_message").click(function(){var tourist = getcookie("tourist");var content_div = $("#content"); var self_message = $("#sending").val();var NowDateTime = getNowFormatDate();if(self_message){var data = {username : tourist,content  : self_message,send_time: NowDateTime}my_websocket.emit("message",data);$("#sending").val("") ;}else{alert("不能发送空消息");}});});$('.emotion').qqFace({id : 'facebox', assign:'sending', path:'arclist/' //表情存放的路径});});
//正则替换表情
function replace_em(str){str = str.replace(/\</g,'<');str = str.replace(/\>/g,'>');str = str.replace(/\n/g,'<br/>');str = str.replace(/\[em_([0-9]*)\]/g,'<img src="arclist/$1.gif" border="0" />');return str;
}
//将信息放在滚动条最下面
function scrollWindow(){var t = document.getElementById('content');t.scrollTop = t.scrollHeight;
}
function clearAll()
{$("content").html("");var newHtml = "<a href=\"#\" οnclick=\"clearAll()\" id=\"clearAll\" style=\"float:right\">清空记录</a>";$("#content").html(newHtml);
}
</script>
</body>
</html>

服务器端 的源码:

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);app.get('/',function(req,res){res.send('<h1>Welcome Realtime Server</h1>');
});var userArr = new Array();var userCount = 0;
io.on('connection',function(socket)
{console.log('a user connected');socket.on('login',function(obj){//判断是否是新用户登录  indexOf是js 判断数组是否包含一个元素的函数 大于0表示包含 -1表示不包含if(userArr.indexOf(obj) == '-1'){userArr.push(obj);userCount ++;}var login_message ={user_array : userArr,user_count : userCount,user_now   : obj}console.log(login_message);//将所有用户登录的信息发给所有用户io.sockets.emit('login_message',login_message);});socket.on('message',function(msg){console.log('接收到',msg);io.sockets.emit('message',msg);});socket.on('logout',function(obj){console.log(obj+'已退出');//判断是否是新用户登录  indexOf是js 判断数组是否包含一个元素的函数 大于0表示包含 -1表示不包含if(userArr.indexOf(obj) >= '0'){for(var i= 0;i<userArr.length;i++){if(userArr[i] == obj){//1. splice(1,1)   -删除第二个元素。////第一个 1 是位置, 位置从0 开始;////第二个1 是个数, 删除一个元素。userArr.splice(i,1);}}userCount --;}var logout_message ={user_array : userArr,user_count : userCount,user_now   : obj}console.log("logout");console.log(logout_message);socket.broadcast.emit('logout_message',logout_message);});
});
http.listen(3000,function(){console.log('listening on *:3000');
});

websocket以及nodejs联手打造的类qq群聊天室 教程 附 原代码相关推荐

  1. 使用nodejs+Socket打造P2P实现多人聊天室

  2. java qq聊天界面_【附源码】用Java写了一个类QQ界面聊天小项目,可在线聊天!...

    原标题:[附源码]用Java写了一个类QQ界面聊天小项目,可在线聊天! 目录: 1.功能实现 2.模块划分 3.使用到知识 4.部分代码实现 5.运行例图 1.功能实现 1.修改功能(密码.昵称.个性 ...

  3. 最新引流技巧:利用QQ秀聊天室日引1000+IP

    现在已经不是"酒香不怕巷子深"的时代了,我们的网站或产品再好,也需要用户来发现,不然,都是空谈.今天给大家分享一个最新的引流方式,希望对大家有帮助,只要你肯做,日引流1000+IP ...

  4. Nodejs+socket.io 搭建个人的网页聊天室

    Nodejs+socket.io 搭建个人的网页聊天室 最近看到别人搭建了自己的实时聊天室便产生了兴趣,于是乎自己也着手搭建了一个.在socket这里我选用了socket.io这个模块,在网上看了很多 ...

  5. websocket 学习--简单使用,nodejs搭建websocket服务器,到模拟股票,到实现聊天室

    websocket简介: WebSocket协议是 HTML5 开始提供的一种基于TCP的一种新的全双工通讯的网络通讯协议.它允许服务器主动发送信息给客户端. 和http协议的不同?? HTTP 协议 ...

  6. 基于JavaFX的类QQ的聊天工具

    一. 功能描述 现在,聊天工具的普及使得信息传递越来越方便,像QQ与微信这样的聊天工具已经可以说是占据了这个行业的半边天,逐渐成为人们日常生活工作间离不开的工具. 因此本次我基于javafx+网络编程 ...

  7. 基于Qt的类QQ气泡聊天的界面开发(三)

    最近在写IM 聊天界面,想设计出一个类似QQ气泡聊天的样式 使用了几种办法 1:使用Qt下面的QListview来实现QQ类似效果,差强人意 2:使用QWebview加载html css样式来完成,发 ...

  8. 基于Qt的类QQ气泡聊天的界面开发

    最近在写IM 聊天界面,想设计出一个类似QQ气泡聊天的样式 使用了几种办法 1:使用Qt下面的QListview来实现QQ类似效果,差强人意 2:使用QWebview加载html css样式来完成,发 ...

  9. Fms3和Flex打造在线多人视频会议和视频聊天(附原代码)

    Flex,Fms3系列文章导航 Flex,Fms3相关文章索引 本篇是视频聊天,会议开发实例系列文章的第3篇,该系列所有文章链接如下: http://www.cnblogs.com/aierong/a ...

最新文章

  1. Python 中 function(#) (X)格式 和 (#)在Python3.*中的注意
  2. WebSocket实战之————GatewayWorker使用笔记例子
  3. 运维笔记 - Nginx
  4. 科研|本科来自普通二本的博士3年迎来2篇Nature,创造校史!
  5. 附加数据库后登陆报错
  6. php代码审计小技巧
  7. 共享文件夹只能连接20人_英语正能量 | 快乐可以与人共享,苦难却只能自己坚强...
  8. C# 一次性获取二维数组中的一维数组数据
  9. PowerBuilder9.0 安装包及注意事项
  10. 数据库中左连接、右连接、内连接与外连接的区别和作用
  11. 一句话木马上传常见的几种方法
  12. 艾永亮:优衣库,究竟是怎么卖衣服的?
  13. 神兵利器——敏感文件发现工具
  14. Android 11.0 修改添加的默认文件夹为9宫格样式
  15. 数据库存储过程怎么写
  16. 人类想要拥有金钱、权力、美丽、永生、幸福……但海龟只想做一只海龟
  17. 对YAML :: LoadFile的未定义引用
  18. 计算机等级二级公共基础
  19. 世界上还有人以“厕所”为姓,都知道是哪国人
  20. 中国电信4g最快服务器IP,中国电信DNS IP地址大全(32个省)

热门文章

  1. python之HTMLParser解析HTML文档
  2. discuz目录结构 ano
  3. 树莓派3 基于Ubuntu mate 16.04的调用中文输入法
  4. flea-auth使用之权限子模块介绍
  5. 核磁共振、顺磁共振、磁共振成像这些原理你都了解吗
  6. 【证券】什么是开仓、持仓和平仓?
  7. java add event handler_最佳的addEvent事件绑定是怎样诞生的
  8. tomcat下webapps目录里ROOT文件删除掉一招恢复
  9. 百度云盘不限速下载工具(附带开源源码)
  10. Java面试之搜狐畅游COO面试之惨败