Original address: http://www.moye.me/2015/01/02/node_socket-io/
Introduction
Recently heard a question: Socket.io How to achieve private chat? In other words: How to locate the person (end), or how to identify the connection, rather than rely on the socket.id of each connection. Good question.
Under the guidance of Socket.io real-time WEB application development, the following ideas are formed:
- The server generates SESSION_ID when each user enters the system for the first time
- Service-side force user to enter nickname, corresponding to session_id
- The Socket.io of the server can be obtained when connected,
socket.request.headers.cookie
parse out the session_id from this cookie, and correspond the socket connection to the session_id in the context of the web framework.
- Use an array on the server to hold the corresponding relationships that are generated by the above three:
[{name, session_id, socket} , ...]
- With an array of correspondence, you can locate people and distinguish [me] from [others], and you can use a saved socket for private chats.
With the idea, you can practice it:
Server Side
ES6 generator is too good to use, do Node Web start from KOA. Well, my package.json seems to have these dependent libraries:
"Co": "^4.0", "KOA": "^0.14.0", "Koa-mount": "*", "Koa-ejs": "*"," Koa-static ":" * "," Koa-router ":" * "," koa-session ":" * "," co-body ":" * "
User List
The list of users mentioned in the idea is a simple array: The [{name, session_id, socket} , ...]
operation around it is also very simple (Sockethandler:
//interfaces exposed to the WebModule.exports.addUser =AddUser; Module.exports.otherUsers=otherusers;varUsers = [];functionFindinusers (session_id) {//Find by session_id varindex =-1; for(varj = 0, len = users.length; J < Len; J + +) { if(users[j].session_id = = =session_id) Index=J; } returnindex;}functionaddUser (name, session_id) {varindex =findinusers (session_id); if(Index = = =-1)//does not exist then add againUsers.push ({name:name, session_id:session_id, Socket:NULL}); Else{//Update only Nicknames if(Users[index].name!==name) Users[index].name=name; }}functionSetusersocket (session_id, socket) {//Update user Socket varindex =findinusers (session_id); if(Index!==-1) {Users[index].socket=socket; }}functionFinduser (session_id) {varindex =findinusers (session_id); returnIndex >-1? Users[index]:NULL;}functionOtherusers (session_id) {//Other People varResults = []; for(varj = 0, len = users.length; J < Len; J + +) { if(users[j].session_id!==session_id) Results.push ({session_id:users[j].session_id, name:users[j].name}); } returnresults;}
Session Store
Koa-session This library provides session storage functionality, which is very simple to use:
var koa = require (' KOA '); var session = require (' koa-session '); var app == [CONFIG. Secret];app.use (session (APP));
In addition, Koa-session will enclose a session_id identity string in the cookie for Web request, koa:sess
so we can use it in the event listener for Socket.io:
function (socket) { var sessionId = GetSessionID (socket.request.headers.cookie, ' KOA: Sess '); if (sessionId) { setusersocket (sessionId, socket); }); function GetSessionID (cookiestring, cookiename) { varnew RegExp (cookiename + ' = ( [^;] +); ', ' Gmi '). EXEC (cookiestring); return NULL ;}
User Login
The so-called login, is to let the user enter a nickname, and it corresponds to the session_id, and stored in the above user array. Assuming our routing path is/chat and the login action path is/chat/login, the route looks like this:
varRouter = require (' Koa-router ')), Router=NewRouter ();varParse = require (' Co-body ');varSockethandler = require ('.. /.. /middlewares/sockethandler ');//Get/chatRouter.get ('/',function*() { varsession_id = This. Cookies.get (' koa:sess '); varName = This. Session.name; if(session_id && name) {//Add to User listsockethandler.adduser (name, session_id); Yield This. Render ('.. /www/views/chat ');//using Ejs}Else { This. Redirect ('/chat/login '); }});//get/chat/login using Ejs templatesRouter.get ('/login ',function*() {yield This. Render ('.. /www/views/login ')});//Post/chat/login Receive form submission: <input name= ' name ' >Router.post ('/login ',function*(){ varBODY = Yield Parse ( This); This. Session.name = Body.name | | ' Guest '; This. Redirect ('/chat ')}); Module.exports= Router;
Broadcast and private chat message processing
Io.on (' Connection ',function(socket) {Socket.on (' Broadcast ',function(data) {//Broadcast varFromuser =Finduser (sessionId); if(Fromuser) {Socket.broadcast.emit (' Broadcast ', {name:fromUser.name, msg:data.msg}); } }); Socket.on (' Private ',function(data) {//private Chat {to_session_id, msg} varFromuser =Finduser (sessionId); if(fromuser) {varTouser =Finduser (data.to_session_id); if(Touser) toUser.socket.emit (' Private ', {name:fromUser.name, msg:data.msg}); } });});
Client
After connecting to the server, the client will periodically pull the list of others:
// get a list of other people regularly function updateothers () { $.post(function (others) { //... Some ugly UI DOM manipulation code setTimeout (updateothers, +); 1000);
Corresponding, the server will have one such interface:
//post/chat/others Other People listRouter.post ('/others ',function*(){ varsession_id = This. Cookies.get (' koa:sess '); varName = This. Session.name; if(session_id &&name) { This. Type = ' Application/json '; This. BODY =sockethandler.otherusers (session_id); } Else { This. Status = 404; }});
Run effect
Run in three different browsers like a chat room that didn't fire in the late 90:)
Source
Complete source stacking on my github: Https://github.com/rockdragon/socketchat, to get it running, you need to get Node up to 0.11.14 (because of the Co V4), of course, the README. The MD has detailed setup instructions.
More articles please visit my blog new address: http://www.moye.me/
[node. js] Private chat based on Socket.io