nodejs 基于socket.io实现聊天室

由于之后要做的网页视频直播项目要用到socket.io模块,所以特地花时间研究了下,参照网上的代码做了些改进,自己写了个聊天室代码。不得不承认后端事实推送能力有点厉害,这是以前我用php一直苦恼的事情。下面简单介绍下我的项目,顺带讲解下nodejs。

事实上,在看别人写的代码之前,我一直不知道nodejs是干嘛的,直到真正接触到才明白这也可以算作是服务端代码,丰富的第三方库使其功能极其强大。它可以像golang的beego一样直接通过命令行开启服务器,不过要用到express模块。加载模块的方式类似php,如下:

var express = require('express'); //引用express

要想开启一个服务器只需以下几行代码即可:

var express = require('express'); //引用express
var app = express();
var server = require('http').Server(app);
//监听服务器启动
server.listen(3000, function() {
	console.log("Express server listening on port " + app.get('port'));
});

在服务器开启成功后用console.log在命令行打印消息,及其方便。

接下来就该定义路由了,事实上nodejs有路由模块,然而我还没研究过那模块具体实现了哪些功能,只借用了别人的代码来写基本的路由,大致形式如下:

app.set('views', __dirname + '/views');
app.get('/', function(req, res) {
	//res.send('hello world');
	res.sendFile(app.get("views") + '/login.html');
	//res.redirect('/login');
});

req即request请求,res即response返回,这与javaweb有些类似。res.send大概是直接输出字符串内容到页面上,而sendFile则是将指定文件的内容输出到页面,redirect即重定向。倘若我在3000端口开启服务器,那么以上代码则规定当我通过get方法访问localhost:3000/时,将views/login.html的内容输出到页面上,其实也就是访问了views/login.html这个页面。app.get中的get即get方法。同样,若要写post请求的接口,则用app.post即可。注:这个app对象即文章开始定义的express对象。

介绍完路由,再来介绍模板。既然nodejs能作为服务端语言来开发,那么自然少不了模板模块。当然,nodejs有很多模板模块,这边我只了解了ejs模块,就先只介绍这。

调用方式如下:

app.set("view engine", "ejs");
//聊天室首页
app.get('/index', function(req, res) {
	res.render("index", {
		"user": req.session.user
	});
});

调用res.render方法来传值到页面,第一个参数即模板页面的名称即views/index.ejs(注意后缀是ejs),第二个参数是附带的数据,既然是js,那附带的数据自然是js下的json数据。注:在nodejs中views和view似乎都有规定,定义页面路径时app.set(‘views‘, __dirname + ‘/views‘);程序运行成功,而app.set(‘view‘, __dirname + ‘/views‘);则会报错,错误原因忘了,反正我查看了英文论坛下的答复才知道是这个问题,定义页面路径时最好还是用views吧。

在模板页面调用也很方便,直接<%=user%>即可。如下:

<input type="hidden" value="<%=user%>" id="user" />

req.session.user是我使用了session模块。因为我的聊天室做了登陆页的,顺便用了下session模块熟悉熟悉。调用方式如下:

var session = require('express-session'); //如果要使用session,需要单独包含这个模块
app.use(session({
	secret: 'ScumVirus',
	name: 'sv_chat', //这里的name值得是cookie的name,默认cookie的name是:connect.sid
	cookie: {
		maxAge: 3600000
	}, //设置maxAge是3600000ms,即1h后session和相应的cookie失效过期
	resave: false,
	saveUninitialized: true,
}));
//设置session
req.session.user = "ScumVirus";
//获取session
var name = req.session.user;

nodejs还提供了加密模块,可以很方便的加密字符串,我一般都用32位md5加密,只介绍获取32位md5加密的方法,如下:

var crypto = require('crypto'); //加密
//获取md5加密后的值
var getMD5 = function(str) {
	var md5 = crypto.createHash('md5');
	md5.update(str);
	var d = md5.digest('hex');
	return d;
}

另外我还用到了mysql模块,用于连接mysql数据库,实现前台注册登陆,调用如下:

var mysql = require("mysql"); //数据库模块
//连接数据库
var connPool = mysql.createPool({
	host: '127.0.0.1', //主机
	user: 'root', //MySQL认证用户名
	password: 'admin', //MySQL认证用户密码
	port: '3306', //端口号
	database: 'sv_chat', //数据库
	waitForConnections: true, //当连接池没有连接或超出最大限制时,设置为true且会把连接放入队列
	//connectionLimit:10,//连接数限制
});
//根据用户获取用户信息
var getUserById = function(name, callback) {
	//执行SQL语句
	var sql = 'select * from sv_user where name=?';
	var params = [name];
	connPool.query(sql, params, function(err, result) {
		if (err) {
			console.log('[SELECT ERROR] - ', err.message);
			return;
		}
		return callback(result[0]);
	});
}
//添加新用户
var addUser = function(params, callback) {
	//执行SQL语句
	var sql = 'insert into sv_user(`name`,`pwd`,`email`,`phone`,`create_time`) values(?,?,?,?,?)';
	connPool.query(sql, params, function(err, result) {
		if (err) {
			console.log('[INSERT ERROR] - ', err.message);
			return callback(false);
		} else {
			console.log('INSERT ID:', result.insertId);
			return callback(true);
		}
	});
}

这边有兴趣的话可以自己打印下查询的结果result,是json格式的数据,有insetId,也有affectedRows,同php几乎一样。不过唯一坑爹的一点是,查询数据库是异步执行的,若要将查询结果返回给前台页面,可能值一直获取不到,这里必须善用回调方法。网上也有介绍说可以线性执行,但是我还没仔细研究过,回调我理解的快,便先用回调函数处理了。

最后是最关键的通信阶段,socket.io模块,后台代码如下:

var io = require('socket.io').listen(server); //socket io模块
//WebSocket连接监听
io.on('connection', function(socket) {
	//socket.emit('open',onlineMember); //通知客户端已连接

	// 打印握手信息
	// console.log(socket.handshake);

	// 构造客户端对象
	var client = {
		name: '',
	}

	// 对message事件的监听
	//登录事件
	socket.on('login', function(name) {
		var time = getTime();
		client.name = name;
		var index = getArrIndex(name,onlineMember);
		if(index == -1){
			onlineMember.push(client.name);
			console.log(time + " " + client.name + " login");
		}
		var obj = {
			time: time,
			author: client.name,
			text: '',
			type: 'login',
			member: onlineMember
		};
		socket.emit('system', obj);
		socket.broadcast.emit('system', obj);
	});
	//消息事件
	socket.on('message', function(msg) {
		var obj = {
			time: getTime(),
		};
		obj['msg'] = msg;
		obj['author'] = client.name;
		obj['type'] = 'message';

		// 返回消息(可以省略)
		socket.emit('message', obj);
		// 广播向其他用户发消息
		socket.broadcast.emit('message', obj);
	});

	//监听退出事件
	socket.on('disconnect', function() {
		var index = getArrIndex(client.name, onlineMember);
		if (index > -1) {
			onlineMember.splice(index, 1);
		}
		var time = getTime();
		var obj = {
			time: time,
			author: client.name,
			text: '',
			type: 'loginout',
			member: onlineMember
		};
		console.log(time + " " + client.name + " loginout");

		// 广播用户已退出
		socket.broadcast.emit('system', obj);
	});
});

前台连接代码:

<script src="/socket.io/socket.io.js"></script>
<script>
	//建立websocket连接
	socket = io.connect('http://localhost:3000');
	var userName = $("#user").val();
	socket.emit('login', userName);
</script>

socket.emit可以理解成双向通信的方法,若客户端A与服务端B连接上了,那么A调用emit方法,则B收到消息,B调用emit方法,则A收到消息。而socket.broadcast.emit方法则是广播,若客户端A,B,C同时连接上服务端D,A通过emit发送消息给D,D接收消息后调用广播方法,则B,C收到消息,而A则收不到消息。login是我自定义的推送消息类型,message是插件本身就定义了的类型,前台可通过socket.send(msg)触发,,disconnect也是插件定义的类型,在客户端断开连接时调用。

最后放上我源代码的下载地址:nodejs聊天室

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-03 22:40:11

nodejs 基于socket.io实现聊天室的相关文章

基于Socket的Android聊天室

1        基于Socket的Android聊天室 Socket通信是网络通信中最常用的技术之一,通过Socket建立的可靠连接,可以让多个终端与服务器保持通信,最典型的应用是建立一个多人聊天程序.本实例使用ServerSocket建立聊天服务器.将服务器端所有的通讯线程保存到一个集合当中,当有用户发来数据,则转发给所有用户,实现聊天室效果.Android端通过使用Socket建立客户端链接,并且在AsyncTask中执行网络读写的任务,将用户输入的内容发送到服务器,并接收服务器发来的数据

Socket.io在线聊天室

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎.chrome浏览器就基于V8,同时打开20-30个网页都很流畅.Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低.非常适合小型网站,个性化网站,我们自己的Geek网站!! 关于作者 张丹(Conan), 程序员Java,R,PHP,Java

使用 Socket.IO 开发聊天室

前言 Socket.IO 是一个用来实现实时双向通信的框架,其本质是基于 WebSocket 技术. 我们首先来聊聊 WebSocket 技术,先设想这么一个场景: · 用户小A,打开了某个网站的充值界面,该界面上有一个付款的二维码. · 当小A 用某宝的 APP 扫码付款之后,网页要自动跳转到付款成功的界面.最简单的方法就是网页每隔一段时间就请求一次服务器--"怎么样?那货付款没有?","怎么样?还没付吗?","怎么样?这次总该付了吧". ·

Node.js+socket.io在线聊天室

Node.js+socket.io实现在线聊天室,照着这个教程做的,稍加改动即可实现. Node.js:0.10.31 Express:3.* 创建工程chat: 添加几个文件,工程结构如下 代码: package.json: { "name": "application-name", "version": "0.0.1", "private": true, "scripts": { &

node.js + socket.io实现聊天室一

前段时间,公司打算在社区做一个聊天室.决定让我来做.本小白第一次做聊天类功能,当时还想着通过ajax请求来实现.经过经理提示,说试试当前流行的node.js 和socket.io来做.于是就上网学习研究起来. 首先,先看一下node.js.本小白当时还以为是一个什么js的框架或者类库.结果才知道,原来完全不是那么回事. node.js 诞生于2009年,是一种轻量级的web服务.如果查看node.js的官网,真的非常简答,简短的几行代码,就搭建了一个web服务. var http = requi

使用nodejs+express+socketio+mysql搭建聊天室

使用nodejs+express+socketio+mysql搭建聊天室 nodejs相关的资料已经很多了,我也是学习中吧,于是把socket的教程看了下,学着做了个聊天室,然后加入简单的操作mysql数据库存聊天记录.express主要是做了路由及jade模板.我是用的国外的免费空间托管的,国内各种备案,它的访问地址是:nodejs聊天室http://chat.lovewebgames.com/,效果图如下: 用到的插件如下: "socket.io":"~1.3.5&quo

分享基于 websocket 网页端聊天室

博客地址:https://ainyi.com/#/67 有一个月没有写博客了,也是因为年前需求多.回家过春节的原因,现在返回北京的第二天,想想,应该也要分享技术专题的博客了!! 主题 基于 websocket 网页端聊天室 WebSocket 协议是基于 TCP 的一种新的网络协议.它实现了浏览器与服务器全双工 (full-duplex) 通信--允许服务器主动发送信息给客户端. 使用 java 开发后台 需要导入一个jar包:javax.websocket-api-1.0-rc4.jar 后台

java socket控制台版本聊天室程序源码下载

原文:java socket控制台版本聊天室程序源码下载 代码下载地址:http://www.zuidaima.com/share/1550463257578496.htm java socket控制台版本聊天室程序源码下载,学习的时候写的,适合学习java基础 java网络编程基础用 标签: java socket 控制台 聊天室 源码话题: 网络编程 java socket控制台版本聊天室程序源码下载,布布扣,bubuko.com

基于flask的网页聊天室(二)

基于flask的网页聊天室(二) 前言 接上一次的内容继续完善,今天完成的内容不是很多,只是简单的用户注册登录,内容具体如下 具体内容 这次要加入与数据哭交互的操作,所以首先要建立相关表结构,这里使用flask-sqlalchemy来辅助创建 首先修改之前的init文件为: from flask import Flask from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() from web_chatroom.models impor