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聊天室






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要实现一个基于 Node.js 和 Socket.io 的多人聊天室,可以按照以下步骤: 1. 安装 Node.js 和 Socket.io 在命令行中输入以下命令安装 Node.js 和 Socket.io: ``` npm install node npm install socket.io ``` 2. 创建服务器 创建一个 `server.js` 文件作为服务器,引入 Node.js 和 Socket.io: ```javascript const http = require('http'); const socketIO = require('socket.io'); ``` 创建一个 HTTP 服务器: ```javascript const server = http.createServer((req, res) => { res.writeHead(200, {'Content-Type': 'text/html'}); res.end('<h1>Hello World!</h1>'); }); ``` 启动服务器: ```javascript server.listen(3000, () => { console.log('Server started on port 3000'); }); ``` 3. 创建 Socket.io 实例 创建一个 Socket.io 实例并将其连接到 HTTP 服务器上: ```javascript const io = socketIO(server); ``` 4. 处理连接和断开事件 当有客户端连接到服务器时,Socket.io 会触发 `connection` 事件: ```javascript io.on('connection', (socket) => { console.log('A user connected'); }); ``` 当客户端断开连接时,Socket.io 会触发 `disconnect` 事件: ```javascript socket.on('disconnect', () => { console.log('A user disconnected'); }); ``` 5. 实现聊天功能 当客户端发送消息时,服务器会将消息广播给所有连接的客户端: ```javascript socket.on('chat message', (msg) => { io.emit('chat message', msg); }); ``` 当客户端连接时,服务器会将欢迎消息广播给所有连接的客户端: ```javascript io.emit('chat message', 'A user has joined the chat'); ``` 当客户端断开连接时,服务器会将离开消息广播给所有连接的客户端: ```javascript io.emit('chat message', 'A user has left the chat'); ``` 6. 客户端实现 在客户端 HTML 文件中,引入 Socket.io: ```html <script src="/socket.io/socket.io.js"></script> ``` 连接到服务器: ```javascript const socket = io(); ``` 发送消息: ```javascript $('form').submit(() => { socket.emit('chat message', $('#m').val()); $('#m').val(''); return false; }); ``` 接收消息: ```javascript socket.on('chat message', (msg) => { $('#messages').append($('<li>').text(msg)); }); ``` 这样,一个基于 Node.js 和 Socket.io 的多人聊天室就完成了。 ### 回答2: Node.js是一个基于事件驱动的JavaScript运行环境,可以用于服务端应用程序的开发。Socket.io是一个基于WebSocket的协议的实时通信库,它可以让浏览器和服务端建立持久的双向通信连接。 要实现一个多人聊天室,可以使用Node.js和Socket.io来建立服务端和客户端之间的通信。下面是大致的步骤: 1. 服务端的配置: - 使用npm安装Node.js和Socket.io。 - 创建一个Node.js的服务器,并引入Socket.io库。 - 在服务器上监听客户端的连接事件,当有新的客户端连接时,建立与其的Socket连接。 - 在Socket连接上监听客户端发送的消息,并将其广播给所有连接到服务器的客户端。 2. 客户端的配置: - 在HTML文件中引入Socket.io库。 - 在JavaScript文件中创建Socket对象,建立与服务器的连接。 - 在Socket连接上监听服务器发送的消息,并将其显示在页面上。 通过以上的步骤,就可以实现基本的多人聊天室了。当有新的客户端连接到服务器时,服务器会给所有客户端发送一个欢迎消息。当某个客户端发送消息时,服务器会将该消息广播给所有客户端,以实现消息的同步。 当然,这只是一个简单的示例。在实际应用中,我们可能还需要处理用户认证、私聊功能、展示在线用户列表等额外的功能。 总而言之,使用Node.js和Socket.io可以轻松实现多人聊天室,同时提供实时通信的功能。它们的简洁和高效性使得开发实时应用变得更加容易。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值