SSH聊天

哈Ha 控制台聊天是一件很了不起的事情,但是对于前端来说,如果想要一样的话,对于后端来说又会怎样呢? 如果是,那么本文适合您。 但是后端经常使用哪种工具? 没错,ssh,所以我代表sshchat。


看起来如何


在服务器上的某个位置,节点上的程序正在旋转。
只要有人想连接到聊天,他就会输入:


ssh server -p 8022 

之后,系统会要求输入密码,并使用特殊文件中的密码进行验证。 如果密码匹配,则我们连接到聊天室(该用户收到100条先前的消息,其他人看到他已连接)。


然后,他收到其他人的消息,并可以编写自己的消息。


这里带有更有趣的消息:


 @box{@color(red){Red text in box}} 

在框中发送红色文本。


让我们开始吧


要使用ssh,我们将使用https://www.npmjs.com/package/ssh2
对于格式化,我们使用粉笔和Boxen。
因此安装它们:


 npm i ssh2 chalk boxen 

现在,代码本身是此消息解析器( GitHub )中最重要的部分之一:


 //  chalk  boxen const chalk = require('chalk'); const boxen = require('boxen'); //         @ //   2           let methods = { color: function(args, text) { return chalk.keyword(args)(text); }, bold: function(args, text) { return chalk.bold(text); }, underline: function(args, text) { return chalk.underline(text); }, hex: function(args, text) { return chalk.hex(args)(text); }, box: function(args, text) { return boxen(text, { borderStyle: 'round', padding: 1, borderColor: 'blueBright' }); } }; //   function parseAndExecute(str) { let pos = 0; let stage = 0; let nS = ''; let bufs = ['', '', '', '']; let level = 0; while (pos < str.length) { let symbol = str[pos]; pos++; if (symbol == '\\' && '(){}@'.indexOf(str[pos]) !== -1) { bufs[stage] += str[pos]; pos++; continue; } if (stage == 0 && symbol == '@') { stage++; nS += bufs[0]; bufs[0] = ''; continue; } else if (stage >= 1) { if (symbol == '(') if (stage < 2) { stage = 2; } else { level++; } if (symbol == ')' && stage >= 2 && level > 0) level--; if (symbol == '{') if (stage != 3) { stage = 3; } else { level++; } if (symbol == '}') { if (level == 0) { bufs[3] += '}'; nS += methods[bufs[1]](bufs[2].slice(1, -1), parseAndExecute(bufs[3].slice(1, -1))); bufs = ['', '', '', '']; stage = 0; continue; } else { level--; } } } bufs[stage] += symbol; } return nS + bufs[0]; } module.exports.parseAndExecute = parseAndExecute; 

格式( GitHub ):


 const chalk = require('chalk'); const { parseAndExecute } = require('./parserExec') //  (    ) function getNick(nick) { let hash = 0; for (var i = 0; i < nick.length; i++) hash += nick.charCodeAt(i) - 32; return chalk.hsv((hash + 160) % 360, 90, 90)(chalk.bold(nick)); } module.exports.format = function(nick, message) { const nickSpace = '\r ' + ' '.repeat(nick.length); nick = getNick(nick) + ': '; message = message.replace(/\\n/gm, '\n'); //  \n   message = parseAndExecute(message) //  //       message = message .split('\n') .map((e, i) => '' + (i !== 0 ? nickSpace : '') + e) .join('\n'); return nick + message; }; 

向所有用户发送消息并保存100条消息的方法( GitHub ):


 let listeners = []; //   let cache = new Array(100).fill('') //  //     module.exports.addListener = write => listeners.push(write) - 1; module.exports.delListener = id => listeners.splice(id, 1); //   module.exports.broadcast = msg => { cache.shift() cache.push(msg) process.stdout.write(msg) listeners.forEach(wr => wr(msg)); } //   module.exports.getCache = ()=>cache.join('\r\033[1K') 

大厅,服务器创建和授权( GitHub ):


 const { Server } = require('ssh2'); const { readFileSync } = require('fs'); const hostKey = readFileSync('./ssh'); //   const users = JSON.parse(readFileSync('./users.json')); //  let connectionCallback = () => {}; module.exports.createServer = function createServer({ lobby }) { //   const server = new Server( { banner: lobby, //      hostKeys: [hostKey] }, function(client) { nick = ''; client .on('authentication', ctx => { //  if (ctx.method !== 'password') return ctx.reject(); if (ctx.password !== users[ctx.username]) ctx.reject(); nick = ctx.username; ctx.accept(); }) .on('ready', function() { connectionCallback(client, nick); }); } ); return server }; module.exports.setConnectCallback = callback => { //     connectionCallback = callback; }; 

各种方法( GitHub ):


 const { createInterface } = require('readline'); module.exports.getStream = function(client, onStream, onEnd){ client //     .on('session', function(accept, reject) { accept() .on('pty', accept => accept & accept()) .on('shell', accept => onStream(accept())); }) .on('end', () => onEnd()); } //   module.exports.getCommunicator = function(stream, onMessage, onEnd){ let readline = createInterface({ //     input: stream, output: stream, prompt: '> ', historySize: 0, terminal: true }) readline.prompt() readline.on('close', ()=>{ radline = null; onEnd() stream.end() }) readline.on('line', (msg)=>{ stream.write('\033[s\033[1A\033[1K\r') onMessage(msg) readline.prompt() }) //     return msg=>{ stream.write('\033[1K\r' + msg) readline.prompt() } } 

现在结合( GitHub ):


 const { createServer, setConnectCallback } = require('./lobby'); const { getStream, getCommunicator } = require('./utils'); const { addListener, delListener, broadcast, getCache } = require('./broadcaster'); const { format, getNick } = require('./format'); //    module.exports = function({ lobby = 'Hi' } = {}) { const server = createServer({ lobby }); setConnectCallback((client, nick) => { //   console.log('Client authenticated!'); let id = null; getStream( //   client, stream => { const write = getCommunicator( //   stream, msg => { if (msg == '') return; try { broadcast(format(nick, msg) + '\n'); //    ,    } catch (e) {} }, () => {} ); id = addListener(write); //   write('\033c' + getCache()); //   broadcast(getNick(nick) + ' connected\n'); //    }, () => { delListener(id); broadcast(getNick(nick) + ' disconnected\n') //    } ); }); server.listen(8022); }; 

最后一步是一个示例服务器:


 const chat = require('.') chat({}) 

users.json文件还描述了用户及其密码。


结论


这是您不能在ssh中编写最简单的聊天方式的方法。
对于这样的聊天,客户端不需要编写,它具有设计功能,任何人都可以部署它。


还有什么可以做的:


  • 添加创建自己的设计功能的功能
  • 添加降价支持
  • 添加机器人支持
  • 提高密码安全性(哈希和盐)

最终仓库

Source: https://habr.com/ru/post/zh-CN466633/


All Articles