Node.js+Express+Socket.IO搭建在线聊天室-程序员宅基地

技术标签: 笔记  Node.js  

1.聊天问题图解:

首先:用户聊天是通过Socket.IO完成的,和Express框架没有多大关系。最多就是同时监听同一个端口。


2.既然是通过Socket.IO进行聊天,那么就必须有服务器端和客户端。如图:

其他服务器端和客户端都是一个普通的js文件而已。(这里我就以 : chat.js为客户端 。  talk.js为服务器端)

其实服务器端和客户端的函数大致都是一一对应的。如:

(1):客户端进入了聊天页面,则发送一条登录信息给服务器,服务器接收即可。方法名都是一一对应。

所以依次类推(2),(3),(4)都是同样的道理。只不过是服务器发送数据给客户端还是客户端发送给服务器的问题。

注意:emit是提交数据。 on是接收数据。


3.有了客户端和服务器端,再加上一个聊天页面我们就可以拼凑一个聊天室了。如图:

我们从外层来看是这样的:



4.最后一个问题是文件的位置如何放置,以及监听Express的端口。文件主要是talk.js的位置。我放在了与app.js相同的目录下。所以配置如下:

(1)./bin/www文件的监听如下:

(2).talk.js文件代码:

var io = require('socket.io')();

// 用户列表
var userlist = [];

io.sockets.on('connection', function(socket) {
	// 用户登录聊天室
	socket.on('login' , function(data){
		var k = lookuser(data.userid);
		if (  k >= 0 ){
			userlist[k].userid = data.userid;
			userlist[k].socket = this;
			userlist[k].friendid = data.friendid;
		}else{
			userlist[userlist.length] = {socket:this , userid:data.userid , friendid : data.friendid};
		}
	});
	// 聊天
	socket.on('chat', function(data) {
		var content = data.content;
		var userid = data.userid;
		var friendid = data.friendid;
		var k = lookuser(friendid);
		if ( k >= 0 ){
			sio = userlist[k].socket;
			if ( userlist[k].friendid == userid ){//用户与自己聊天   发送数据
				sio.emit('showcontent', {
					content: content ,
				});
			}else {
				sio.emit('messagenew', {//用户在线,但不与自己聊天,发送信息和提示信息
					title : '您有一条新的消息!',
					content: content,
					friendid : userid
				});
			}
		}else{
			socket.emit('sendmessage', {//用户不在。发送信息
				content: content,
				friendid : friendid
			});
		}
	}); 
	socket.on('logout', function(data) {//退出聊天室
		var userid = data.userid;
		var k = lookuser(userid);
		if ( k >= 0 ){
			userlist.splice(k , 1);
		}
	});
});

function lookuser(userid){//查看用户是否在线
	for ( var i = 0  , len = userlist.length ; i < len ; i ++ ){
		if ( userlist[i].userid == userid ){
			return i;
		}
	}
	return - 1;
}
exports.listen = function(_server){
	io.listen(_server);
};

(3)客户端chat.js代码如下:

window.onload =function(){
	var socket = io.connect();
	var messagelist = document.getElementById('chatlist');
	var message = document.getElementById('message');
    var sendbt = document.getElementById('send_bt');
    var sendmessagebox = document.getElementById('sendmessagebox');
    var user = {
    	userid:document.getElementById('userid').value , 
    	usernickname:document.getElementById('usernickname').value,
    	userimg:document.getElementById('userimg').value
    };
    var friend = {
    	friendid:document.getElementById('friendid').value , 
    	friendnickname:document.getElementById('friendnickname').value,
    	friendimg:document.getElementById('friendimg').value
    };
    socket.emit('login' , {userid:user.userid , friendid:friend.friendid});
    // 获取聊天数据
	socket.on('showcontent', function(data) {
        var value = data.content;
        var issend = data.issend;
        messagelist.innerHTML +='<div class="comment_item"><div class="comment_friend_img"><img src="../'+friend.friendimg+'" alt=""></div><div class="comment_friend_content"><div class="friend_sj"></div><p>'+value+'</p></div></div>';
   		window.scrollTo(0 , document.body.scrollHeight);
    });
    // 发送提示消息
    socket.on('messagenew' , function(data){
    	var value = data.content;
        var sendid = data.friendid;
        var title = data.title;
        sendmessagebox.style.display = 'block';
        if ( sendid ){
        	$.ajax({
        	  type: 'POST',
        	  url: '/message/sendmessage',
        	  data: JSON.stringify({ userid: user.userid , friendid : sendid , content: value }),
  			  contentType: 'application/json'
        	});
        }
        var url = "/chat/"+sendid;
        sendmessagebox.innerHTML = '<a href="'+url+'">'+title+'</a>';
        setTimeout(function(){
        	sendmessagebox.style.display = 'none';
        } , 5*1000);
    });
    // 对方不在,发送消息
    socket.on('sendmessage', function(data) {
        var value = data.content;
        var friendid = data.friendid;
        if ( friendid == friend.friendid ){
        	$.ajax({
        	  type: 'POST',
        	  url: '/message/sendmessage',
        	  data: JSON.stringify({ userid: friend.friendid , friendid: user.userid , content: value }),
  			  contentType: 'application/json'
        	});
        }
    });
    // 提交聊天数据
    sendbt.addEventListener('click' , function(){
    	if ( message.value.trim() == '' ) 
    		return;
    	socket.emit('chat', {content: message.value , userid:user.userid , friendid:friend.friendid});
    	var text = message.value;
    	messagelist.innerHTML +='<div class="comment_item"><div class="comment_user_img"><img src="../'+user.userimg+'" alt=""></div><div class="comment_user_content"><div class="user_sj"></div><p>'+text+'</p></div></div>';
    	message.value ='';
    	window.scrollTo(0 , document.body.scrollHeight);
    });
    window.onbeforeunload = function(){
	    socket.emit('logout' , {userid:user.userid});
    };
};
 

(4)chat.jade的代码如下



5.至此基本上所有的都完成了。只要把Express路由器配置好能访问chat.jade即可。最后我们再来看一下目录结构




总结:


以为本人开发所需,加入了其他的功能。所以代码变得比较繁琐。有不对的地方麻烦您提出,再次表示感谢!!!!!!!!


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yjy188/article/details/44925651

智能推荐

vsCode 代码不高亮显示的问题_vscode ssh 不高亮-程序员宅基地

安装Vetur插件点击左侧菜单的扩展--》搜索Vetur--》点击安装--》安装完成重启vsCode_vscode ssh 不高亮

java枚举的父类_Java 之 枚举(Enum)-程序员宅基地

一、枚举1、概述枚举:JDK1.5引入的,类似于穷举,一一罗列出来Java 枚举:把某个类型的对象,全部列出来枚举类型的对象是有限、固定的几个常量对象。2、应用什么情况下会用到枚举类型?当某个类型的对象是固定的,有限的几个,那么就可以选择使用枚举。在整个系统的运行期间,有且只有这几个对象。例如: 性别类:只有两个对象:男,女季节类:有4个对象:春、夏、秋、冬二、JDK1.5之前,实现枚举效果1、需..._java枚举类型共同父类

openstack-3-程序员宅基地

openstack架构定义OpenStack是由美国国家宇航局(NASA)和RackSpace合作开发的旨在为共有云和私有云提供软件的开源项目,其目的在于提供可靠的云部署方案及良好的可扩展性。简单的说OpenStack就是云操作系统,或者说是云管理平平台,自身并不提供云服务,只是提供部署和管理平平台。openstack的架构OpenStacK是开源的云管理平台,由各个相互独立的模..._openstack-3

动画重定向技术分析和Unity中的应用-程序员宅基地

http://www.jianshu.com/p/6e9ba1b9c99e因为一些手游项目需要使用Unity引擎,但在动画部分需要使用重定向技术来实现动画复用,考虑到有些项目开发人员没有过这方面的经验,下面就给大家介绍下在unity中使用动画重定向技术,一起来看看吧。0. 前言新的手游项目使用Unity引擎,动画部分要使用重定向技术来实现动画复用。之前在大公司工作的时候

JAVA反序列化基于常见框架/中间件回显方案_中间件反序列化-程序员宅基地

0x00概述JAVA反序列化漏洞是JAVA中最常见的可以直接获取目标权限的漏洞,通过反序列化回显的思路也是越来越多,如通过远程加载回显、在目标网站写文件、通过URLClassLoader回显、借助dnslog回显等。这些思路多少都有些瓶颈。一旦遇到了目标因网络策略严格无法出外网,则需要借助Dnslog的打法效果会失效,如果可以直观的返回命令执行结果,那岂不是更香?0x01知识点Tomcat处理流程在tomcat自己实现的Servlet处打断点,观察tomcat调用栈大致执行流程:调用过程_中间件反序列化

Lumen 安装配置-程序员宅基地

一、lumen安装安装器安装1. composer global require "laravel/lumen-installer"2. lumen new blogcomposer 安装参考 https://blog.csdn.net/root_miss/article/details/802472622、复制env 给一个 APP_KEY=qGBWykk9mGBtwzq...

随便推点

以退为进还是被逼无奈?创始人王劲离职后,景驰科技该何去何从?-程序员宅基地

【数据猿导读】对于王劲的离职,业内有诸多猜测:有人说,因为百度的诉讼,让不到一周岁的景驰科技被推到了风口浪尖,董事会一气之下把王劲赶了出来;也有人说,王劲是以退为进,百度此举是针对王劲,而并非景驰科技,为了景驰科技未来的合作和融资,王劲先退出以保景驰科技“周全”。记者 | 郭敏官网 | www.datayuan.cn微信公众号ID | datayuancn日前,有消息称景驰科技创始人兼CEO王劲已

华为ar2200series配置手册_思科ASA系列防火墙配置手册-程序员宅基地

思科ASA系列防火墙配置手册思科ASA系列防火墙配置手册使用console连接线登录方法 1.使用cisco的console连接线,连接设备的console口和计算机com口(笔记本用USB转COM口连接线)2.使用超级终端或secureCRT软件连接设备 串行选项: 波特率:9600 数据位:8 奇偶校验:无 停止位:1 数据流控制: RTS/CTS 登陆设备后,基本配置命令与cisco路由器保..._华为ar2200 series

NSData NSURL 字符串网络请求的时候 互相转换_如何将 网络url 转换成nsdata-程序员宅基地

NSString / NSData / char* 类型之间的转换1. NSString转化为UNICODE String:(NSString*)fname = @“Test”;char fnameStr[10];memcpy(fnameStr, [fname cStringUsingEncoding:NSUnicodeStringEncoding], 2*([fname len_如何将 网络url 转换成nsdata

第 四 周 write up (BJDCTF-2020-Web-Cookie is so subtle! Bugku 蹭网先解开密码 [网鼎杯 2020 青龙组]AreUSerialz nmap)_ctfhubcookie is so subtle!-程序员宅基地

BJDCTF-2020-Web-Cookie is so subtle!(twig,ssti)先百度瞎测了一下,居然测出给git泄露了?跑了下脚本,不是git泄露。 淦重新开始在hint下面发现了提示在flag.php页面登陆后,抓包发现,cookie里面多了变量user。看了大佬的提示:是模板注入,靠,这怎么想得到啊。菜鸡我是真的涨姿势了。如果输入{{7*’7’}}如果 输出7777777 则是jinja2模板 如果是 49 则是 twig模板这里输出了4_ctfhubcookie is so subtle!

开源项目 | 一款 SpringBoot 互联网企业级开源支付系统-程序员宅基地

点击“终码一生”,关注,置顶公众号每日技术干货,第一时间送达!今天分享给大家一个聚合支付相关的开源项目,有需要的小伙伴,可以收藏了!1项目介绍 Jeepay是一套适合互联网企业使...

批处理脚本实现Aida64测试工具的System Stability Test项目自动测试-程序员宅基地

批处理脚本实现Aida64测试工具的System Stability Test项目自动测试自动测试脚本编写背景:因为最近要使用Aida64测试工具的System Stability Test项目测试整机的稳定性能,整机数量总共有100台不可能一台台去点击Aida64工具进行测试,后面写了个批处理脚本,省去大量点击操作时间1、Aida64测试工具下载网址:https://pan.baidu..._system stability test