nodeJs socketJs 搭建长连接(2) 项目应用整合
来源:互联网 发布:软件项目经验范文 编辑:程序博客网 时间:2024/06/07 00:43
今天我们在这里要说的是wehsocket和node开发长连接问题,我们在真正的项目中,可能要实现的功能不知是简单的聊天功能,我们现在要整合redis,rabbitMQ,等实现o2o的提醒功能:
首先,整合一次redis:
我们建立一个chat文件夹,在其中写入一个package.json文件,用于生成我们的node类库
{ "name": "zefun", "version": "1.0.0", "description": "", "main": "index.js", "dependencies": { "apn": "^1.5.2", "amqp": "^0.2.4", "co": "^3.0.6", "co-redis": "^1.1.1", "log4js": "^0.6.28", "express": "^4.13.3", "redis": "^0.10.3", "redis-sentinel": "^0.1.3", "socket.io": "^1.3.7" }, "devDependencies": {}, "author": "", "license": "ISC"}这时,我们通过运行node的命令进行安装类库,npm install
安装结束后,我们会生成一个node_modules的文件,还要在本层的目录创建一个logs的文件夹,因为我们一会会使用一个日志系统进行输出,但是,node只有写文件的权限,没有输出文件夹的权限
新建一个redisClient.js,作为redis的客户端连接
var PORT = 6379;var HOST = '120.25.254.164';var redis = require('redis');var chatClient = redis.createClient(PORT,HOST);var logger = require("./log").logger("redis");chatClient.on('error', function(err){logger.error(err);});var chat_sadd = function(key, field) {chatClient.sadd(key, field);logger.info("redis sadd --> key : " + key + ", field : " + field);}var chat_srem = function(key, field) {chatClient.srem(key, field);logger.info("redis srem --> key : " + key + ", field : " + field);}var chat_smembers = function(key) {return chatClient.smembers(key);}var chat_hset = function(key, userId, sockedId) {chatClient.hset(key, userId, sockedId);logger.info("redis hset --> key : " + key + ", field : " + userId + ", value :" + sockedId);} var chat_hget = function(key, userId) {return chatClient.hget(key, userId);} exports.chat_sadd = chat_sadd;exports.chat_srem = chat_srem;exports.chat_smembers = chat_smembers;exports.chat_hset = chat_hset;exports.chat_hget = chat_hget;
下面我们在主js中进行引用和传值即可
var co = require('co');var wrapper = require('co-redis');var redis = wrapper(require("./redisClient"));我们看到上面我们使用了一个叫co的类库,并使用wrapper对redis进行了包装,只有经过包装,在操作redis的时候,才能处理了node中异步的程序,将redis取值变成了同步的方式,即取到值后才能进行下面程序的执行
co(function* () {<span style="white-space:pre"></span>var userSID = yield redis.chat_hget(USER_SOCKET_KEY, toUser);io.sockets.connected[userSID].emit('getMessage',{msg:msg});})();对于存值不需要这么同步
redis.chat_sadd(redis_key,data.userId);redis就算是结束了,下面就开始rabbitMQ的搭建和操作:
此处我们将node作为了rabbit的一个client进行监听和处理程序,首先新建一个mqClient.js作为队列的客户端进行监听
conn.queue('queue_chat_notify', { autoDelete: false, durable: true }, function(queue) { queue.subscribe(function (msg) { receiveNotify(msg.data); }); }); exports.createConnection = function(r1, r2) { receiveLogout = r1; receiveNotify = r2; }这是我们最核心的进行监听的程序,是要subscribe这个方法,就可以进行监听了,请注意receiveLogout这个方法,我们这个方式是需要在主js中作为参数传入的,当客户端进行传入一个方法作为替代方法的时候,就可以进行读取消息,但是如果没有传入,那么该条数据丢失.下面是主js中的代码
var mq = require("./mqClient");mq.createConnection(receiveNotify);//rabbitmq监听到通知的回调操作var receiveNotify = function(msg) {logger.info("\r\n\r\n<-- receiveNotify begin -->");sendMsg(msg);}这样,在客户端中判定登陆后,启用该方法就可以读取队列中的消息,进行发送消息了,下面给出整个mqClient.js的全部内容
var amqp = require("amqp");var exchName = "directExchange";var connOptions = { host: '120.25.254.164', port: 5672, login: 'zefun', password: 'zefun' };var exchOption = { type: 'direct', durable: true, autoDelete: false, confirm: false };var conn;var receiveNotify = null;var logger = require('./log').logger("rabbitmq");conn = amqp.createConnection(connOptions);conn.on('ready',function() { logger.info("rabbitmq is ready ... "); conn.queue('queue_chat_notify', { autoDelete: false, durable: true }, function(queue) { queue.subscribe(function (msg) { logger.info("queue_chat_notify consumer msg : " + msg); receiveNotify(msg.data); }); });});conn.on('close', function(){ logger.error("rabbitmq is close");});conn.on('error', function (error) { logger.error('Connection error : ' + error);});exports.createConnection = function(r1) { logger.info("createConnection r1 : " + r1); receiveNotify = r1;}exports.publish = function(routeKey, message) { conn.publish(routeKey, message);};下面就是我们最后一步,看一下servier.js中的内容了
var app = require('express')();var http = require('http').Server(app);var io = require('socket.io')(http);app.get('/', function(req, res){ res.send('<h1>Welcome Realtime Server</h1>');});http.listen(3000, function(){ console.log('listening on *:3000');});var mq = require("./mqClient");var co = require('co');var wrapper = require('co-redis');var redis = require("./redisClient");var redisClient = wrapper(redis.chatClient);var logger = require("./log").logger("server");var STORE_USER_KEY = "store_to_chat_user_set_";var USER_SOCKET_KEY = "chat_user_to_socket_hash";//rabbitmq监听到通知的回调操作var receiveNotify = function(msg) {logger.info("\r\n\r\n<-- receiveNotify begin -->");sendMsg(msg);}mq.createConnection(receiveNotify);io.on('connection', function (socket) { io.sockets.emit('connect',{hello:'connection success'}); socket.on('sendMsg', function (from,toUser,msg,msgType) { co(function* () { var userSID = yield redisClient.hget(USER_SOCKET_KEY, toUser); io.sockets.connected[userSID].emit('getMessage',{msg:msg}); })(); }); socket.on('initUser',function(data){ var redis_key = STORE_USER_KEY + data.storeId; //redis插入数据 redisClient.sadd(redis_key,data.userId); redisClient.hset(USER_SOCKET_KEY, data.userId, socket.id); logger.info('initUser --->> 门店 :' + data.storeId + ', 用户 : ' + data.userId); }); socket.on('disconnect', function () { });});var sendMsg = function(obj){co(function* () { var socketId = yield redisClient.hget(USER_SOCKET_KEY, obj.toUser); logger.info("socketId : " + socketId); io.sockets.connected[socketId].emit("getMessage", obj);})(); }下面,我们写一个客户端,其实就是一个jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><% String chatPath = request.getContextPath();String chatPasePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()+ chatPath + "/";%><script src="<%=chatPath%>/js/common/socket.io.js"></script><script type="text/javascript">var userId = '${session_key_user_id}';var storeId = '${session_key_store_id}';var user = {"userId" : userId, "storeId" : storeId};if(!isEmpty(userId)){var socket = io.connect('ws://localhost:3000'); socket.on('connect', function(data) { //登录聊天室 socket.emit('initUser', user); //接收消息 socket.on('getMessage', function(data) { console.log("" + data); var fid = data.fid; //PC通知类处理 if (fid == 2) { var type = data.data.type; //新预约 if (type == 2) { //播放语音 textToVoice(0, data.data.msg); } } }); });}</script>可以进行触发登陆,然后进行接收消息即可了.
记得在linux上启动的时候 , 使用 forever start server.js 命令进行启动,可作为守护进程,这样node就不会随着终端的关闭而down掉。。。
到此我们的整套就写完了,最后注意一下日志,如果我们想将现在的类库导入成为package.json的话,在文件夹中使用npm init,自动生成json文件,就可以进行移植
给出一个该项目的下载链接地址 http://download.csdn.net/detail/u014201191/9303347
#特别注意:
在本案例中 io.sockets.connected[socket.id].emit("method",msg) 和 io.sockets.sockets[socket.id].emit("method",msg) 这两个方法都不可用,可以换成: io.to[socket.id].emit("method",msg) 触发传送事件了,好像是TM因为版本的问题。。。
- nodeJs socketJs 搭建长连接(2) 项目应用整合
- nodeJs socketJs 搭建长连接(1) 基础讲解
- socketIo 搭建长连接(2)
- eclipse nodejs项目搭建
- 延长Nodejs HTTP 的连接时长
- socketIo 搭建长连接(1)
- nodeclipse 搭建nodejs项目图解
- 使用express搭建nodejs项目
- nodejs项目环境的搭建
- Nodejs 手动搭建 Express 项目
- 【SSM整合】-项目搭建
- Ajax长连接项目案例
- nodejs socket长连接服务端和测试客户端
- NodeJS和Socket.IO搭建聊天室应用
- MQTT客户端搭建及应用(Nodejs)
- 搭建一个nodejs项目 使用express
- intellij IDEA创建nodejs项目---环境搭建
- intellij IDEA创建nodejs项目---环境搭建
- 代理,动态代理
- linux下bluetooth编程(六)L2CAP层编程实例
- dB是如何定义的,dBm与W之间的关系
- DLL 类型
- 【百度地图api·javascript】入门,在web中创建和使用百度地图api
- nodeJs socketJs 搭建长连接(2) 项目应用整合
- 关于tableView的复用
- [UIViewController _loadViewFromNibNamed:bundle:] loaded the "One" nib but the view outlet was not se
- ngnix tomcat7 memcache集群session配置系列---环境配置
- Linux创建指定用户特定指定目录权限
- spark graphX求最短路径以及中间结点
- Form Data 转换成 Request Palyload
- Gitolite安装使用
- openSession和getCurrentSession