socketIo Builds Long Connections (2)

Keywords: Redis socket RabbitMQ JSON

Today we're going to talk about wehsocket and node development long connection. In a real project, we may want to achieve a function that is not a simple chat function. Now we need to integrate it. Redis Rabbit MQ, etc. implements o2o's reminder function:

First, integrate a redis:

We create a chat folder in which we write a package.json file to generate our node class library

{  
  "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"  
}  
At this point, we install the class library by running the node command, npm install

After installation, we will generate a node_modules file, and create a logs folder in the directory of this layer, because we will use a log system for output later, but node only has the right to write files, not the right to output folders.

Create a new redisClient.js as a client connection to redis

  1. var PORT = 6379;  
  2. var HOST = '120.25.254.164';  
  3. var redis = require('redis');  
  4. var chatClient = redis.createClient(PORT,HOST);  
  5. var logger = require("./log").logger("redis");  
  6. chatClient.on('error', function(err){  
  7.     logger.error(err);  
  8. });  
  9. var chat_sadd = function(key, field) {  
  10.     chatClient.sadd(key, field);  
  11.     logger.info("redis sadd --> key : " + key + ", field : " + field);  
  12. }  
  13. var chat_srem = function(key, field) {  
  14.     chatClient.srem(key, field);  
  15.     logger.info("redis srem --> key : " + key + ", field : " + field);  
  16. }  
  17. var chat_smembers = function(key) {  
  18.     return chatClient.smembers(key);  
  19. }  
  20. var chat_hset = function(key, userId, sockedId) {  
  21.     chatClient.hset(key, userId, sockedId);  
  22.     logger.info("redis hset --> key : " + key + ", field : " + userId + ", value :" + sockedId);  
  23. }   
  24. var chat_hget = function(key, userId) {  
  25.     return chatClient.hget(key, userId);  
  26. }   
  27.   
  28. exports.chat_sadd = chat_sadd;  
  29. exports.chat_srem = chat_srem;  
  30. exports.chat_smembers = chat_smembers;  
  31. exports.chat_hset = chat_hset;  
  32. exports.chat_hget = chat_hget
Now we can refer to and pass values in the main js
  1. var co = require('co');  
  2. var wrapper = require('co-redis');  
  3. var redis = wrapper(require("./redisClient"));
We saw above that we used a class library called co and wrapper to wrap redis. Only after wrapping can we handle the asynchronous program in node when we operate redis. We can change redis value into synchronous way, that is, after getting the value, we can execute the following program.

  1. co(function* () {  
  2. <span style="white-space:pre">    </span>var userSID = yield redis.chat_hget(USER_SOCKET_KEY, toUser);  
  3.     io.sockets.connected[userSID].emit('getMessage',{msg:msg});  
  4. })(); 
There is no need for such synchronization for stored values

  1. redis.chat_sadd(redis_key,data.userId);  
Even if redis is over, let's start the construction and operation of rabbitMQ.

Here we use node as a client of rabbit to listen and process. First, we create a new mqClient.js to listen as the client of the queue.

  1. conn.queue('queue_chat_notify', { autoDelete: false, durable: true }, function(queue) {  
  2.     queue.subscribe(function (msg) {  
  3.       receiveNotify(msg.data);  
  4.     });  
  5.   });  
  6.   exports.createConnection = function(r1, r2) {  
  7.     receiveLogout = r1;  
  8.     receiveNotify = r2;  
  9.   } 
This is the core of our monitoring program, is to subscribe this method, you can listen, please note receiveLogout this method, we need to pass in as parameters in the main js, when the client to pass in a method as an alternative method, you can read the message, but if not, then the data is lost. Here is the main J. The code in S

  1. var mq = require("./mqClient");  
  2. mq.createConnection(receiveNotify);  
  3. //The callback operation of rabbitmq to monitor the notification
  4. var receiveNotify = function(msg) {  
  5.     logger.info("\r\n\r\n<-- receiveNotify begin -->");  
  6.     sendMsg(msg);  
  7. }  
In this way, after deciding the login in the client, the message in the queue can be read and sent by using this method. The whole content of mqClient.js is given below.

  1. var amqp = require("amqp");  
  2.   
  3. var exchName = "directExchange";  
  4.   
  5. var connOptions = {  
  6.       host: '120.25.254.164',  
  7.       port: 5672,  
  8.       login: 'zefun',  
  9.       password: 'zefun'  
  10.     };  
  11.   
  12. var exchOption = {  
  13.       type: 'direct',  
  14.       durable: true,  
  15.       autoDelete: false,  
  16.       confirm: false  
  17.     };  
  18.   
  19. var conn;  
  20. var receiveNotify  = null;  
  21. var logger = require('./log').logger("rabbitmq");  
  22. conn = amqp.createConnection(connOptions);  
  23.   
  24. conn.on('ready',function() {  
  25.   logger.info("rabbitmq is ready ... ");  
  26.   conn.queue('queue_chat_notify', { autoDelete: false, durable: true }, function(queue) {  
  27.     queue.subscribe(function (msg) {  
  28.       logger.info("queue_chat_notify consumer msg : " + msg);  
  29.       receiveNotify(msg.data);  
  30.     });  
  31.   });  
  32. });  
  33.   
  34. conn.on('close', function(){  
  35.   logger.error("rabbitmq is close");  
  36. });  
  37.   
  38. conn.on('error', function (error) {  
  39.   logger.error('Connection error : ' + error);  
  40. });  
  41.   
  42. exports.createConnection = function(r1) {  
  43.   logger.info("createConnection r1 : " + r1);  
  44.   receiveNotify = r1;  
  45. }  
  46. exports.publish = function(routeKey, message) {  
  47.   conn.publish(routeKey, message);  
  48.   
  49. };  

Here's our final step. Let's take a look at what's in servier.js.

  1. var app = require('express')();  
  2. var http = require('http').Server(app);  
  3. var io = require('socket.io')(http);  
  4.   
  5. app.get('/', function(req, res){  
  6.     res.send('<h1>Welcome Realtime Server</h1>');  
  7. });  
  8.   
  9. http.listen(3000, function(){  
  10.     console.log('listening on *:3000');  
  11. });  
  12.   
  13. var mq = require("./mqClient");  
  14.   
  15. var co = require('co');  
  16. var wrapper = require('co-redis');  
  17. var redis = require("./redisClient");  
  18. var redisClient = wrapper(redis.chatClient);  
  19.   
  20. var logger = require("./log").logger("server");  
  21.   
  22. var STORE_USER_KEY = "store_to_chat_user_set_";  
  23. var USER_SOCKET_KEY = "chat_user_to_socket_hash";  
  24.   
  25. //The callback operation of rabbitmq to monitor the notification
  26. var receiveNotify = function(msg) {  
  27.     logger.info("\r\n\r\n<-- receiveNotify begin -->");  
  28.     sendMsg(msg);  
  29. }  
  30.   
  31. mq.createConnection(receiveNotify);  
  32.   
  33. io.on('connection', function (socket) {  
  34.   
  35.   io.sockets.emit('connect',{hello:'connection success'});  
  36.   socket.on('sendMsg', function (from,toUser,msg,msgType) {  
  37.      co(function* () {  
  38.          var userSID = yield redisClient.hget(USER_SOCKET_KEY, toUser);  
  39.          io.sockets.connected[userSID].emit('getMessage',{msg:msg});  
  40.      })();   
  41.   });  
  42.   
  43.   socket.on('initUser',function(data){  
  44.      var redis_key = STORE_USER_KEY + data.storeId;  
  45.   
  46.      //redis insert data
  47.      redisClient.sadd(redis_key,data.userId);  
  48.      redisClient.hset(USER_SOCKET_KEY, data.userId, socket.id);  
  49.   
  50.      logger.info('initUser --->> store :' + data.storeId + ', user : ' + data.userId);  
  51.   });  
  52.   
  53.   socket.on('disconnect', function () {  
  54.         
  55.   });  
  56. });  
  57.   
  58. var sendMsg = function(obj){  
  59.     co(function* () {  
  60.          var socketId = yield redisClient.hget(USER_SOCKET_KEY, obj.toUser);  
  61.          logger.info("socketId : " + socketId);  
  62.          io.sockets.connected[socketId].emit("getMessage", obj);  
  63.     })();   
  64. }  

Next, we write a client, which is actually a jsp file.

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <%  
  4.     String chatPath = request.getContextPath();  
  5.             String chatPasePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()  
  6.                     + chatPath + "/";  
  7. %>  
  8. <script src="<%=chatPath%>/js/common/socket.io.js"></script>  
  9. <script type="text/javascript">  
  10. var userId = '${session_key_user_id}';  
  11. var storeId = '${session_key_store_id}';  
  12. var user = {"userId" : userId, "storeId" : storeId};  
  13. if(!isEmpty(userId)){  
  14.     var socket = io.connect('ws://localhost:3000');  
  15.     socket.on('connect', function(data) {  
  16.         //Log in to the chat room.
  17.         socket.emit('initUser', user);  
  18.           
  19.         //Receive messages
  20.         socket.on('getMessage', function(data) {  
  21.             console.log("" + data);  
  22.             var fid = data.fid;  
  23.             //PC Notification Class Processing
  24.             if (fid == 2) {  
  25.                 var type = data.data.type;  
  26.                 //New appointment
  27.                 if (type == 2) {  
  28.                     //Play voice.
  29.                     textToVoice(0, data.data.msg);  
  30.                 }  
  31.             }  
  32.         });  
  33.     });  
  34. }  
  35. </script>  
You can trigger the login and receive the message.

Remember in Linux Up to boot time Start with a command that acts as a daemon so that the node does not go down as the terminal closes...

At this point, our whole set is finished. Finally, note the log. If we want to import the class libraries into package.json, we can use npm init in the folder to generate JSON files automatically and transplant them.

Give a download link address for the project http://download.csdn .NET/detail/u014201191/9303347

# Special attention should be paid to:

In this case, neither io.sockets.connected[socket.id].emit("method",msg) nor io.sockets.sockets[socket.id].emit("method",msg) is available. Instead, io.to[socket.id].emit("method",msg) triggers the transmission event, as if TM is due to version problems.

Posted by rj2kix on Fri, 19 Apr 2019 23:27:35 -0700