{"id":200866,"date":"2013-11-05T16:04:03","date_gmt":"2013-11-05T12:04:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=200866"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=200866","title":{"rendered":"<span class=\"post_title\">\u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 \u0447\u0430\u0442 \u043d\u0430 Node.JS<\/span>"},"content":{"rendered":"<div class=\"content html_format\"> \t\t\t\u0414\u0430, \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u043f\u043e\u043b\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0447\u0430\u0442\u0430, \u043d\u043e \u0432\u0441\u0435-\u0436\u0435 \u043c\u043d\u0435 \u043e\u043d\u0438 \u043d\u0435 \u043f\u043e \u0434\u0443\u0448\u0435. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0412\u0430\u043c \u043c\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0430\u0442\u0430, \u0441 \u0431\u043b\u0435\u043a\u0434\u0436\u0435\u043a\u043e\u043c \u0438 \u0441\u0430\u043c\u0438 \u0437\u043d\u0430\u0435\u0442\u0435 \u0447\u0435\u043c.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u0441\u0440\u0430\u0437\u0443 <a href=\"http:\/\/x.cloudx.cx\/simplechat\/main.html\">\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0434\u0435\u043c\u043e<\/a> \u0434\u043b\u044f \u043d\u0435\u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u044b\u0445.<\/p>\n<h4>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438<\/h4>\n<p>  <\/p>\n<ul>\n<li>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u0411\u0414<\/li>\n<li>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f<\/li>\n<li>\u041a\u043e\u043c\u0430\u043d\u0434\u044b \u0447\u0430\u0442\u0430<\/li>\n<li>\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043f\u043e WebSocket<\/li>\n<\/ul>\n<p>  <a name=\"habracut\"><\/a><\/p>\n<h4>\u041a\u0430\u043a \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/h4>\n<p>  \u041d\u0443 \u0442\u0443\u0442 \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e<br \/>  <img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/ff4\/0ac\/897\/ff40ac89762434411ede4870db72124b.png\"\/><\/p>\n<h4>\u041a\u0430\u043a \u0442\u0430\u043a\u043e\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c<\/h4>\n<h5>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/h5>\n<pre><code class=\"bash\">sudo yum install nodejs sudo yum install mongodb npm install ws npm install mongodb <\/code><\/pre>\n<h5>\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u0443\u0435\u043c<\/h5>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0443\u044e \u0447\u0430\u0441\u0442\u044c, \u043f\u043e\u043a\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f node.js \u0438 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439.<\/p>\n<p>  HTML \u0432\u0435\u0441\u044c\u043c\u0430 \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u0435\u043d<\/p>\n<pre><code class=\"html\">&lt;!DOCTYPE html&gt; &lt;html&gt; \t&lt;head&gt; \t\t&lt;link href='http:\/\/fonts.googleapis.com\/css?family=Ubuntu&subset=latin,cyrillic' rel='stylesheet' type='text\/css'&gt; \t\t&lt;link href=&quot;main.css&quot; rel=&quot;stylesheet&quot; \/&gt; \t\t&lt;script src=&quot;main.js&quot; defer&gt;&lt;\/script&gt; \t\t&lt;meta charset=&quot;UTF-8&quot;&gt; \t&lt;\/head&gt; \t&lt;body&gt; \t\t&lt;form id=&quot;loginform&quot; class=&quot;unauthorized&quot;&gt; \t\t\t&lt;input id=&quot;login&quot; placeholder=&quot;\u041b\u043e\u0433\u0438\u043d&quot;&gt;&lt;br&gt; \t\t\t&lt;input id=&quot;password&quot; placeholder=&quot;\u041f\u0430\u0440\u043e\u043b\u044c&quot;&gt; \t\t\t&lt;div&gt;* \u0415\u0441\u043b\u0438 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d&lt;\/div&gt; \t\t&lt;\/form&gt; \t\t&lt;output id=&quot;messages&quot;&gt;&lt;\/output&gt; \t\t&lt;div&gt; \t\t\t&lt;div contenteditable id=&quot;input&quot;&gt;&lt;\/div&gt; \t\t&lt;\/div&gt; \t&lt;\/body&gt; &lt;\/html&gt; <\/code><\/pre>\n<p>  \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0443 <code>defer<\/code> \u0443 \u0442\u0435\u0433\u0430 <code>script<\/code>, javascript \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u0441\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b. \u042d\u0442\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435, \u0447\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>window.onload<\/code><\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u043a\u043e\u0434, \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u043c <code>document.getElementById<\/code> \u0434\u043e <code>$<\/code><\/p>\n<pre><code class=\"javascript\">function $(a){return document.getElementById(a)} <\/code><\/pre>\n<p>  \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0438 \u0436\u0434\u0451\u043c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<pre><code class=\"javascript\">ws = new WebSocket ('ws:\/\/x.cloudx.cx:9000');  ws.onmessage = function (message) { \t\/\/ \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043c \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432 \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u044b\u0439 \u0432\u0438\u0434  \tvar event = JSON.parse(message.data); \t \t\/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \tswitch (event.type) { \t\tcase 'message': \t\t\t\/\/ \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043c \u0441\u0430\u043c\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \t\t\t \t\t\tvar name = document.createElement('div'); \t\t\tvar icon = document.createElement('div'); \t\t\tvar body = document.createElement('div'); \t\t\tvar root = document.createElement('div'); \t\t\t \t\t\tname.innerText = event.from; \t\t\tbody.innerText = specials_in(event); \t\t\t \t\t\troot.appendChild(name); \t\t\troot.appendChild(icon); \t\t\troot.appendChild(body); \t\t\t \t\t\t$('messages').appendChild (root); \t\t\t \t\t\tbreak; \t\tcase 'authorize': \t\t\t\/\/ \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0431 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \t\t\tif (event.success) { \t\t\t\t$('loginform').classList.remove('unauthorized'); \t\t\t} \t\t\tbreak; \t\tdefault:  \t\t\t\/\/ \u0435\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043f\u044f\u0442\u0438\u043b, \u0442\u043e \u0434\u0430\u0435\u043c \u043e\u0431 \u0441\u0435\u0431\u0435 \u044d\u0442\u043e\u043c \u0437\u043d\u0430\u0442\u044c \t\t\tconsole.log ('unknown event:', event) \t\t\tbreak; \t} } <\/code><\/pre>\n<p>  \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u044b \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>specials_in<\/code>. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u0449\u0435\u0442 \u0432 \u0442\u0435\u043a\u0441\u0442\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b, \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0447\u0430\u0442\u0430.<\/p>\n<pre><code class=\"javascript\">function specials_in (event) { \tvar message = event.message; \tvar moment = new Date(event.time); \t         \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0440\u0435\u043c\u044f \u0432 \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u043e\u043c \u0432\u0438\u0434\u0435 \tvar time = (moment.getHours()&lt;10)? '0'+moment.getHours() : moment.getHours(); \t\ttime = (moment.getMinutes()&lt;10)? time+':0'+moment.getMinutes() : time+':'+moment.getMinutes(); \t\ttime = (moment.getSeconds()&lt;10)? time+':0'+moment.getSeconds() : time+':'+moment.getSeconds(); \tvar date = (moment.getDate()&lt;10)? '0'+moment.getDate() : moment.getDate(); \t\tdate = (moment.getMonth()&lt;10)? date+'.0'+moment.getMinutes()+'.'+moment.getFullYear() : date+':'+moment.getMonth()+'.'+moment.getFullYear() \t \t \tmessage = message.replace(\/\\[time\\]\/gim, time); \tmessage = message.replace(\/\\[date\\]\/gim, date); \t \treturn message; } <\/code><\/pre>\n<p>  \u041f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<pre><code class=\"javascript\">function specials_out(message) { \t\/\/ \/me \tmessage = message.replace(\/\\s*\\\/me\\s\/, $('login').value+' '); \t \treturn message; } <\/code><\/pre>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u0442\u0443\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/\/ \u043f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044e Enter \u0432 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f   $('password').onkeydown = function (e) {     if (e.which == 13) {         \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 authorize \t\tws.send (JSON.stringify ({ \t\t\ttype: 'authorize', \t\t\tuser: $('login').value, \t\t\tpassword: $('password').value \t\t}));     } } \/\/ \u043f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044e Enter \u0432 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 $('input').onkeydown = function (e) { \t\/\/ \u0435\u0441\u043b\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a \u043d\u0430\u0436\u0430\u043b Ctrl+Enter \u0438\u043b\u0438 Shift+Enter, \u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443.  \tif (e.which == 13 && !e.ctrlKey && !e.shiftKey) {         \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 message \t\tws.send (JSON.stringify ({ \t\t\ttype: 'message', \t\t\tmessage: specials_out($('input').innerText) \t\t}));  \t\t$('input').innerText = ''; \/\/ \u0447\u0438\u0441\u0442\u0438\u043c \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430     } } \/\/ \u0441\u043a\u0440\u043e\u043b\u043b\u0438\u043c \u0432\u043d\u0438\u0437 \u043f\u0440\u0438 \u043d\u043e\u0432\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 var observer = new MutationObserver(function(mutations) { \tmutations.forEach(function(mutation) { \t\tvar objDiv = $('messages'); \t\tobjDiv.scrollTop = objDiv.scrollHeight; \t});  }).observe($('messages'), { childList: true }); <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438<\/p>\n<p>  \u0421\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u043c\u0441\u044f \u0441 \u0411\u0414 \u0438 \u0436\u0434\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0443 \u043d\u0430 9000 \u043f\u043e\u0440\u0442\u0443<\/p>\n<pre><code class=\"javascript\">\/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 var WebSocketServer = require('ws').Server, \twss = new WebSocketServer({port: 9000});  \/\/ \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0411\u0414 var MongoClient = require('mongodb').MongoClient, \tformat = require('util').format;     var userListDB, chatDB;  \/\/ \u043f\u043e\u0434\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u043c\u0441\u044f \u043a \u0411\u0414 MongoClient.connect('mongodb:\/\/127.0.0.1:27017', function (err, db) { \tif (err) {throw err} \t \t\/\/ \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u044b (\u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438) \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \tuserListDB = db.collection('users'); \tchatDB = db.collection('chat'); }); <\/code><\/pre>\n<p>  \u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0415\u0441\u043b\u0438 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u043d\u0435\u0442, \u0442\u043e \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d. <\/p>\n<pre><code class=\"javascript\">\/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043f\u0440\u0435\u0434\u043c\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 function existUser (user, callback) { \tuserListDB.find({login: user}).toArray(function (error, list) { \t\tcallback (list.length !== 0); \t}); } \/\/ \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0437\u0430 \u0432\u0441\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u043e\u0432 function checkUser (user, password, callback) { \t\/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \texistUser(user, function (exist) { \t\t\/\/ \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \t\tif (exist) { \t\t\t\/\/ \u0442\u043e \u043d\u0430\u0439\u0434\u0435\u043c \u0432 \u0411\u0414 \u0437\u0430\u043f\u0438\u0441\u0438 \u043e \u043d\u0435\u043c \t\t\tuserListDB.find({login: user}).toArray(function (error, list) { \t\t\t\t\/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0430\u0440\u043e\u043b\u044c \t\t\t\tcallback (list.pop().password === password); \t\t\t}); \t\t} else { \t\t\t\/\/ \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0435\u0442, \u0442\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \t\t\tuserListDB.insert ({login: user, password: password}, {w:1}, function (err) { \t\t\t\tif (err) {throw err} \t\t\t}); \t\t\t\/\/ \u043d\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0440\u0430\u0437\u0443 \t\t\tcallback (true); \t\t} \t}); } <\/code><\/pre>\n<p>  \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u043c \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430\u043c \u0447\u0430\u0442\u0430<br \/>  \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u043c \u043b\u0435\u0436\u0430\u0442 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 <code>peers<\/code><\/p>\n<pre><code class=\"javascript\">\/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u043c function broadcast (by, message) { \t \t\/\/ \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u0447\u0442\u043e\u0431 \u043d\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u0432\u0440\u0435\u043c\u044f \tvar time = new Date().getTime(); \t \t\/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044e \tpeers.forEach (function (ws) { \t\tws.send (JSON.stringify ({ \t\t\ttype: 'message', \t\t\tmessage: message, \t\t\tfrom: by, \t\t\ttime: time \t\t})); \t}); \t \t\/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \tchatDB.insert ({message: message, from: by, time: time}, {w:1}, function (err) { \t\tif (err) {throw err} \t}); } <\/code><\/pre>\n<p>  \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<pre><code class=\"javascript\">\/\/ \u043f\u0440\u0438 \u043d\u043e\u0432\u043e\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438  wss.on('connection', function (ws) {\t \t\/\/ \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \tvar login = ''; \tvar registered = false; \t \t\/\/ \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438 \tws.on('message', function (message) { \t\t\/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0432 \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u043e\u043c \u0432\u0438\u0434\u0435 \t\tvar event = JSON.parse(message); \t\t \t\t\/\/ \u0435\u0441\u043b\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a \u0445\u043e\u0447\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0435\u0433\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \t\tif (event.type === 'authorize') { \t\t\t\/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \t\t\tcheckUser(event.user, event.password, function (success) { \t\t\t\t\/\/ \u0447\u0442\u043e\u0431 \u0431\u044b\u043b\u043e \u0432\u0438\u0434\u043d\u043e \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \t\t\t\tregistered = success; \t\t\t\t \t\t\t\t\/\/ \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u043d\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f \t\t\t\tvar returning = {type:'authorize', success: success}; \t\t\t\t \t\t\t\t\/\/ \u0435\u0441\u043b\u0438 \u0443\u0441\u043f\u0435\u0445, \u0442\u043e \t\t\t\tif (success) { \t\t\t\t\t\/\/ \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a \u043e\u0442\u0432\u0435\u0442\u043d\u043e\u043c\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u044e \u0441\u043f\u0438\u0441\u043e\u043a \u043b\u044e\u0434\u0435\u0439 \u043e\u043d\u043b\u0430\u0439\u043d \t\t\t\t\treturning.online = lpeers; \t\t\t\t\t \t\t\t\t\t\/\/ \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0430\u043c\u043e\u0433\u043e \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043b\u044e\u0434\u0435\u0439 \u043e\u043d\u043b\u0430\u0439\u043d \t\t\t\t\tlpeers.push (event.user); \t\t\t\t\t \t\t\t\t\t\/\/ \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0441\u043e\u043a\u0435\u0442 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \t\t\t\t\tpeers.push (ws); \t\t\t\t\t \t\t\t\t\t\/\/ \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0432\u0438\u0434\u043d\u043e \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \t\t\t\t\tlogin = event.user; \t\t\t\t\t \t\t\t\t\t\/\/  \u0435\u0441\u043b\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a \u0432\u044b\u0448\u0435\u043b \t\t\t\t\tws.on ('close', function () { \t\t\t\t\t\tpeers.exterminate(ws); \t\t\t\t\t\tlpeers.exterminate(login); \t\t\t\t\t}); \t\t\t\t} \t\t\t\t \t\t\t\t\/\/ \u043d\u0443 \u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u043e\u0442\u0432\u0435\u0442 \t\t\t\tws.send (JSON.stringify(returning)); \t\t\t \t\t\t\t\/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u0441\u0442\u0430\u0440\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u043c\u0443 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0443 \t\t\t\tif (success) { \t\t\t\t\tsendNewMessages(ws); \t\t\t\t} \t\t\t}); \t\t} else { \t\t\t\/\/ \u0435\u0441\u043b\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a \u043d\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d, \u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u043c \u0435\u0433\u043e \t\t\tif (registered) { \t\t\t\t\/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \t\t\t\tswitch (event.type) { \t\t\t\t\t\/\/ \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \t\t\t\t\tcase 'message': \t\t\t\t\t\t\/\/ \u0440\u0430\u0441\u0441\u044b\u043b\u0430\u0435\u043c \u0435\u0433\u043e \u0432\u0441\u0435\u043c \t\t\t\t\t\tbroadcast (login, event.message) \t\t\t\t\t\tbreak; \t\t\t\t\t\/\/ \u0435\u0441\u043b\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u043d \u043f\u0435\u0447\u0430\u0442\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \t\t\t\t\tcase 'type': \t\t\t\t\t\t\/\/ \u0442\u043e \u043f\u043e\u043a\u0430 \u044f \u043d\u0435 \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0442\u0430\u043a\u0438\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u0445 \t\t\t\t\t\tbreak; \t\t\t\t}\t \t\t\t} \t\t} \t}); }); <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0434\u0430 \u0432\u044b\u0448\u0435 \u0442\u0430\u043a \u0436\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438\u0437 \u0438\u0441\u0442\u043e\u0440\u0438\u0438, \u0441\u043f\u0438\u0441\u043e\u043a \u043b\u044e\u0434\u0435\u0439 \u043e\u043d\u043b\u0430\u0439\u043d \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430<\/p>\n<pre><code class=\"javascript\">\/\/ \u0441\u043f\u0438\u0441\u043e\u043a \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u0447\u0430\u0442\u0430 (\u0438\u0445 \u043b\u043e\u0433\u0438\u043d\u044b) var lpeers = [];  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u0442\u0430\u0440\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043d\u043e\u0432\u043e\u043c\u0443 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0443 \u0447\u0430\u0442\u0430 function sendNewMessages (ws) { \tchatDB.find().toArray(function(error, entries) { \t\tif (error) {throw error} \t\tentries.forEach(function (entry){ \t\t\tentry.type = 'message'; \t\t\tws.send (JSON.stringify (entry)); \t\t}); \t}); }  \/\/ \u0443\u0431\u0440\u0430\u0442\u044c \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u043e \u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e Array.prototype.exterminate = function (value) { \tthis.splice(this.indexOf(value), 1); } <\/code><\/pre>\n<p>  \u0427\u0430\u0442 \u0433\u043e\u0442\u043e\u0432!<\/p>\n<p>  \u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c <a href=\"http:\/\/x.cloudx.cx\/simplechat\/sources.tar.gz\">\u0442\u0443\u0442<\/a><br \/>  (\u0421\u0435\u0440\u0432\u0435\u0440 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u043b\u0435\u0436\u0438\u0442)<\/p>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c<\/p>\n<pre><code class=\"bash\">su - mongod --smallfiles &gt; \/dev\/null & node path\/to\/server.js &gt; \/dev\/null & <\/code><\/pre>\n<h4>TODO<\/h4>\n<p>  <\/p>\n<ul>\n<li>\u0417\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u0444\u043b\u0443\u0434\u0430<\/li>\n<li>\u0411\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u043c\u0430\u043d\u0434 \u0447\u0430\u0442\u0430 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u0432<\/li>\n<li>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0430\u0432\u0430\u0442\u0430\u0440\u043e\u043a<\/li>\n<li>\u0417\u0432\u0443\u043a\u043e\u0432\u044b\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/li>\n<li>\u00ab\u041a\u043e\u043c\u043d\u0430\u0442\u044b\u00bb<\/li>\n<li>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/li>\n<li>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0430\u0443\u0434\u0438\u043e \u0438 \u0432\u0438\u0434\u0435\u043e<\/li>\n<\/ul>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/200866\/\"> http:\/\/habrahabr.ru\/post\/200866\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\"> \t\t\t\u0414\u0430, \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u043f\u043e\u043b\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0447\u0430\u0442\u0430, \u043d\u043e \u0432\u0441\u0435-\u0436\u0435 \u043c\u043d\u0435 \u043e\u043d\u0438 \u043d\u0435 \u043f\u043e \u0434\u0443\u0448\u0435. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0412\u0430\u043c \u043c\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0447\u0430\u0442\u0430, \u0441 \u0431\u043b\u0435\u043a\u0434\u0436\u0435\u043a\u043e\u043c \u0438 \u0441\u0430\u043c\u0438 \u0437\u043d\u0430\u0435\u0442\u0435 \u0447\u0435\u043c.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u0441\u0440\u0430\u0437\u0443 <a href=\"http:\/\/x.cloudx.cx\/simplechat\/main.html\">\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0434\u0435\u043c\u043e<\/a> \u0434\u043b\u044f \u043d\u0435\u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u044b\u0445.<\/p>\n<h4>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438<\/h4>\n<p>  <\/p>\n<ul>\n<li>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u0411\u0414<\/li>\n<li>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f<\/li>\n<li>\u041a\u043e\u043c\u0430\u043d\u0434\u044b \u0447\u0430\u0442\u0430<\/li>\n<li>\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043f\u043e WebSocket<\/li>\n<\/ul>\n<p>  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-200866","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/200866","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=200866"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/200866\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=200866"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=200866"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=200866"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}