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

智能推荐

win7 rdp 8.1升级方法-程序员宅基地

win7 rdp 8.1升级方法,需要做的就是下载几个补丁包,安所需如下:windows 7 SP1 已经把rdp 版本升级到8.1.所以建议win7 版本升级到 windows sp 1 ,具体百度。01 KB2574819升级到rdp协议7.1,02 KB285765003 KB2830477 已经更新到rdp8.104 KB2913751 官方讲信用更新到这..._win7 rdp8.1

命令行下编译C#——csc-程序员宅基地

C#基础不扎实,今天开始从头看起!首先在新建个记事本文件,命名为hello.cs,内部代码如下:using System;class Hello{static void Main(){Console.WriteLine("Hello, World");Console.Out.WriteLine("Hello World"); //Console.WriteL

WT2003S-16S播放音乐控制-程序员宅基地

一、协议命令格式二、写操作指令返回码格式三、控制逻辑1、 查询 SPI-FLASH 内音乐文件总数(C3)(7E 03 C3 C6 EF)2、 音量控制命令(7E 04 AE 08 BA EF)3、根据判断SPI-FLASH 内音乐文件总数返回的操作码右移两位是否为零,非零就指定播放模式为单曲循环播放模式 ,零就不做任何处理4、播放暂停命令(AA) (7E 03 AA AD EF)5、停止命令(AB)(7E 03 AB AE EF)6、查询当前外设连接状态(7E 03 CA C

【BUG】shell命令过长用\换行报错_shell 命令太长-程序员宅基地

sh脚本在windos上编写好,上传到linux服务器会报错(sh脚本包含换行符会报错,不包含不报错)。操作系统改变导致格式错误。使用dos2unix转化sh文件即可正常执行。如run.sh文件python run_classify.py \--model_type bert \--model_name_or_path /data/sfang/BertPretrainedModel/torch/chinese_electra_base_discriminator_pytorch/ \--do_shell 命令太长

Kettle(6.0) 参数方式连接数据库_kettle 数据库连接使用参数-程序员宅基地

数据库连接条件(视自己实际情况而定) 数据库: Oracle 主机名称(IP): localhost 或 127.0.0.1 数据库名称(SID):MYORCL 端口号: 1521 用户名: scott 密码: tiger 连接名称(随意):DB_ORA 连接类型:Oracle_kettle 数据库连接使用参数

关于动态链接库DLL文件的一般常识及常见问题解析-程序员宅基地

DLL是Dynamic Link Library的缩写,意为动态链接库。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL 文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可有多个DLL文件,一个DLL文件也可能被几个应用程序所共 用,这样的DLL文件被称为共享D...

随便推点

CSS中的块级元素和行内元素_在css中,块元素可以嵌套在行内元素中使用。-程序员宅基地

文章目录块级元素:block块元素的特点:使用方式:行内元素:inline行内元素的特点:注意问题:使用方式:浮动:float定位:position块级元素:block每个块级元素默认占一行高度,一行内添加一个块级元素后无法一般无法添加其他元素。两个块级元素连续编辑时,会在页面自动换行显示。块级元素一般可嵌套块级元素或行内元素块元素的特点:每个块级元素都是独自占一行高度,行高以及外边距..._在css中,块元素可以嵌套在行内元素中使用。

集合_字典_列表_enumerate()基本知识点总结_enumerate是有序还是无序的-程序员宅基地

一、集合集合:是一个无序的不重复元素序列。1.添加元素:1.s.add( x ) (添加一个元素)2.s.update( x ) 参数可以是列表,元组,字典等,(添加多个元素)2.删除元素:s.remove( x ) x不存在出错s.discard( x ) x不存在不会出错3.数学中的集合运算:参考链接:https://www.jb5..._enumerate是有序还是无序的

打印机 正在删除正在打印怎么也删除不了_打印机打印文档删除不了-程序员宅基地

打印机 第一个文档的状态为:正在删除正在打印,怎么也删除不了解决方案:方法1:1、打印机长时间工作,导致出现问题。单击“开始”-“运行”,打入services.msc ,在服务列表中,找到“Print Spooler”服务把它停止再启动即可。方法2:1、打印机长时间工作,导致出现问题。单击“开始”-“运行”,打入services.msc ,在服务列表中,找到“Print Spooler”..._打印机打印文档删除不了

WordPress写Z网站源码自带数据_小白来学习东西的博客-程序员宅基地

上传源码到宝塔 wp-config.php 配置数据库 地址密码 然后登陆数据库 替换自己的网址 打开 域名输入密码账号 即可进入后台 设置价格之类 后台账号密码 admin123下载地址:https://zxeo.lanzoui.com/iwILGuucw1a...

vector的使用要注意!_使用vector存储socket数量-程序员宅基地

最近写一个并发的服务器程序,一个服务器监听多个端口.多个客户端连接.这么多监听的socket,想到用socket保存.自己写了一个类简单封装了底层的socket.在写类的时候为了能正常用vector,必须要写类的拷贝构造函数和重载等号运算符.但是在运行的时候select总是出现10038错误,这个错误是socket还没有建立.socket指向的空间里面没有内容.反复调试寻找原因,原来是vec_使用vector存储socket数量

XMPP协议学习笔记六(搭建Tigase开发环境)-程序员宅基地

最近事情比较少,抽空研究了一下Tigase,据说