NodeJS+Redis实现Web实时通讯聊天模块

本文介绍了一个使用Node.js、Redis及Socket.IO实现的实时聊天应用程序。该应用包含服务端和客户端代码,能够处理用户连接、消息发送与接收等功能,并通过WebSocket实现实时通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需要安装NodeJS,以及相关包如redis,socket.io等。

服务端node js代码:

var redis_host = '127.0.0.1', redis_port = 6379;
var redis = require("redis"), client = redis.createClient(redis_port, redis_host);

var io = require('socket.io').listen(4000);
io.set('log level', 1);
io.set('transports', ['websocket' ,'flashsocket' ,'htmlfile' ,'xhr-polling' ,'jsonp-polling']);

var online_user_chat_key = "chat:";
var online_user_list_key = "user:list";

var sockets = [];
var user_info_hash = {};
var socket_user_hash = {};

io.sockets.on('connection', function (socket) {

	socket.on('add-user', function(data) {
		var user = JSON.parse(data).user;
		var id_user = user.id;
		user_info_hash[id_user] = user;
		socket_user_hash[socket.id] = id_user;
		client.sadd(online_user_list_key, id_user, function(err, res){
			update_user_list(id_user, socket);
		});
	});

	socket.on('send-message', function(data){
		var msg = JSON.parse(data);
		var id_target = msg.id_target;
		var id_user = msg.id_user;
		var message = msg.message;
		var date_string = msg.date;
		var id_chat = [id_user, id_target].sort().join("_");
		var json = JSON.stringify({ 'id_user': id_user, 'id_target': id_target,  'message': message, 'date': date_string });
		client.lpush(online_user_chat_key + id_chat, json, function(err, res){
			if (undefined != sockets[id_chat]) {
				for (var id_user in sockets[id_chat]){
					for (var socket_id in sockets[id_chat][id_user]) {
						sockets[id_chat][id_user][socket_id].emit('receive-message', json);
					}
	            }
			}
		});
	});

	socket.on("disconnect", function() {
		var user_id = socket_user_hash[socket.id];
		if(undefined != user_id) {
			client.srem(online_user_list_key, user_id, function(){
				update_user_list(user_id, socket);
			});
			for(var id_chat in sockets) {
				for(var id_user in sockets[id_chat]) {
					if(id_user == user_id) {
						delete sockets[id_chat][id_user];
					}
				}
			}
		}
	});

	socket.on("add-socket", function(data) {
		var msg = JSON.parse(data);
		var id_target = msg.id_target;
		var id_user = msg.id_user;
		store_socket(id_user, id_target, socket);
	});
});

function update_user_list(id_user, socket) {
	client.smembers(online_user_list_key, function(error, users) {
		if(users.length > 0) {
			var user_info = {};
			for(var i in users) {
				var user_id = users[i];
				if(undefined != user_info_hash[user_id]) {
					user_info[user_id] = user_info_hash[user_id];
				}
			}
			show_online_users(user_info, id_user, socket);
		}
	});
}

function show_online_users(user_info, id_user, socket) {
	var reply = JSON.stringify({ id_user: id_user, user_info: user_info });
	io.sockets.emit('show-online', reply);
	for(var id_target in user_info) {
		store_socket(id_user, id_target, socket);
	}
}

function store_socket(id_user, id_target, socket) {
	if(id_user != id_target) {
		var id_chat = [id_user, id_target].sort().join("_");
		if (undefined == sockets[id_chat]) {
			sockets[id_chat] = {};
		}
		if (undefined == sockets[id_chat][id_user]) {
			sockets[id_chat][id_user] = {}
		}
		sockets[id_chat][id_user][socket.id] = socket;
	}
}

客户端代码:

<script type="text/javascript" src="http://<?php echo $hostname; ?>:4000/socket.io/socket.io.js"></script>
<script type="text/javascript">

    $(document).ready(function(){
	$('.chat_icon_here img').each(function(){
	    $(this).attr('title', $(this).attr('alt'));
	})
    });

	var info;
	var month = ['Jan', 'Feb', 'Mar', 'Feb', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
	var new_msg_sound;
	soundManager.setup({
	    url: '/sounds/swf/',
	    flashVersion: 9,
	    onready: function() {
		// Ready to use; soundManager.createSound() etc. can now be called.
		new_msg_sound = soundManager.createSound({
		    id: 'sound_new_msg',
		    url: '/sounds/msg.mp3'
		});
	    }
	});

	var chat_logs = {};
	var id_user = '<?php echo $userId; ?>';
	var socket = io.connect('http://<?php echo $hostname; ?>:4000');
	socket.emit('add-user', $.toJSON({ user: <?php echo json_encode($login_user); ?> }));

	socket.on('show-online', function (msg) {
	    var message = $.evalJSON(msg);
	    info = message.user_info;
	    $("#user_list").empty();
	    var user_account = 0;
	    for(var user in info) {
		try {
		    var username = (info[user].first_name)? (info[user].first_name+ " "+ info[user].last_name): info[user].username;
		    var avator = (info[user].avator)? info[user].avator : "/images/chat/chat_9.png";
		    if(user != id_user) {
			//var image = "<li rel='" + user + "'><a href='javascript:show_chat(" +user+ ");' title='" +username+ "' class='showChat' user='" +user+ "'><image src='" +avator+ "' alt='" +username+ "' width='28'></a></li>";
			var image ="<li rel='" + user + "'><span class='chat_photo'><a href='javascript:show_chat(" +user+ ");' class='showChat' title='Click to Chat with " +username+ "' user='"+ user+ "'><image src='" +avator+ "' alt='" +username+ "' width='28' height='28'></a></span><strong>" +username+ "</strong><span class='cl'></span></li>";
			$("#user_list").append(image);
			user_account++;
		    }
		}
		catch(e){}
	    }
	    $("#chat_amount").html(user_account);
	    var id_target = message.id_user;
	    socket.emit('add-socket', $.toJSON({ id_user: id_user, id_target: id_target }));
	});

	$('#message_box').keydown(function(event) {
	    if (event.keyCode == 13) {
		var message = $('#message_box').val().trim();
		if(!message) {
		    return false;
		}
		var id_target = $("#target").attr("rel");
		var date = new Date();
		var year = date.getFullYear()
		var mon = date.getMonth()
		var day = date.getDate()
		var date_string = month[mon] + " "+ day + ", " + year;
		socket.emit('send-message', $.toJSON({ id_target: id_target, id_user: id_user, message: message, date: date_string }));
		if (chat_logs[id_target] == undefined) {
		    chat_logs[id_target] = {};
		}
		if (chat_logs[id_target][date_string] == undefined) {
		    chat_logs[id_target][date_string] = [];
		}
		chat_logs[id_target][date_string].push(id_user+"@_@"+ message);
		$('#message_box').val("");
		return false;
	    }
	});

	socket.on('receive-message', function (msg) {
	    var message = $.evalJSON(msg);
	    //console.log(message);
	    var target = message.id_user;
	    var id_target = message.id_target;
	    var avator = info[target].avator;
	    if(avator == null) {
		avator = "/images/chat/chat_9.png";
	    }
	    var date_string = message.date;
	    var msg_user = info[target].first_name + " " + info[target].last_name;
	    var msg_content = decode_emotion(message.message);
	    if (chat_logs[target] == undefined) {
		chat_logs[target] = {};
	    }
	    if (chat_logs[target][date_string] == undefined) {
		chat_logs[target][date_string] = [];
	    }
	    chat_logs[target][date_string].push(target+"@_@"+msg_content);

	    if( ($('#chat_window').css("display") == "block" && $("#target").attr("rel") ==  target) || ($('#chat_window').css("display") == "block" && $("#target").attr("rel") == id_target) ) {
		$("#chat_content").append(date_string+ "<hr size='1' /><img width='28' height='28' src='"+ avator+ "' alt='"+ msg_user+ "' align='top' /> " + msg_content);
		$("#chat_content").append("<br/>");
		$("#user_list a.showChat[user="+ target+ "] img").css({"border": "0px solid red"});
		$("#chat_content")[0].scrollTop = $("#chat_content")[0].scrollHeight;
	    }
	    else {
		$("#user_list a.showChat[user="+ target+ "] img").css({"border": "2px solid red"});
		if (undefined != new_msg_sound){
		    new_msg_sound.play();
		}
	    }
	});

	function emotion(emo) {
	    if(emo) {
		$("#message_box").val($("#message_box").val() + " [:"+ emo+ "] ");
		$('#chat_icon_all').slideToggle();
		$("#message_box").focus();
	    }
	}

	function decode_emotion(emo) {
		var ret_val = emo.replace(/\[:(([^\]]+))\]/gi, "<img  align='absmiddle' width='35' height='35' src='/images/chat/$1.png' title='$1' alt='$1' />");
		return ret_val;
	}

	function show_chat(id) {
	    var target = id;
	    var username = info[target].first_name + " " + info[target].last_name;
	    var avator = info[target].avator;
	    if(avator == null) {
		avator = "/images/chat/chat_9.png";
	    }
	    if(target != id_user) {
		$("#target").text(username).attr("rel", target);
		var chat_content = "";
		if (chat_logs[target] != undefined) {
		    //console.log(chat_logs);
		    for(date_string in chat_logs[target]) {
			var list = chat_logs[target][date_string];
			for(i=0; i<list.length; i++)  {
			    var tmp = list[i].split("@_@");
			    var message_field = tmp[1];
			    var avator = info[tmp[0]].avator;
			    chat_content += date_string+ "<hr size='1' /><img width='28' height='28' src='"+ avator+ "' alt='"+ username+ "' align='top' /> " + decode_emotion(message_field)+ "<br />";
			}
		    }
		}
		$("#chat_content").html(chat_content);
		$("#user_list a.showChat[user="+ target+ "] img").css({"border": "0px solid red"});
		$('#chat_window').slideToggle(500, function(){
		    $("#chat_content")[0].scrollTop = $("#chat_content")[0].scrollHeight;
		});
	    }
	}

	function logout_user() {
	    socket.emit('disconnect');
	}
</script>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值