nodejs tls模块,用于没有浏览器的服务器 - 客户端通信

时间:2017-05-19 15:50:11

标签: node.js ssl

我希望使用nodejs在客户端和远程服务器(只是IP地址和端口)之间来回安全地发送消息。客户端运行本地.js文件,不使用浏览器。我尝试使用节点TLS模块(https://nodejs.org/api/tls.html)这样做。

握手工作得非常好,但我无法设法从服务器向客户端发送消息。我目前的代码是:

client.js

const tls = require('tls');
const fs = require('fs');

const options = {
  host: <server IP address>,
  port: <port number>,
  key: fs.readFileSync('client.key'),
  cert: fs.readFileSync('client.crt'),
  ca: fs.readFileSync('ca.crt'),
  checkServerIdentity: function (host, cert) {
    return undefined;
  }  
};

const client = tls.connect(options, function(){
  if (client.authorized) {
    console.log("Connection authorized");
  } else {
    console.log("Connection not authorized: " + conn.authorizationError)
  }
  process.stdin.pipe(client);
  process.stdin.resume();
  client.emit('data','message')
});

client.setEncoding('utf8');

client.addListener('data', function(data) {
   console.log(data);
});

client.on('end', () => {
  server.close();
});

server.js

const tls = require('tls');
const fs = require('fs');

const options = {
  key: fs.readFileSync('server.key'),
  cert: fs.readFileSync('server.crt'),
  ca: fs.readFileSync('ca.crt'), 
  requestCert: true, 
  rejectUnauthorized: true  
};

const server = tls.createServer(options, function(socket){
  console.log('server connected',
              socket.authorized ? 'authorized' : 'unauthorized');
  socket.setEncoding('utf8');
  socket.pipe(socket);
  socket.emit('data','I am the server')
});

server.listen(<port number>,function(){
  console.log('listening')

})

server.on('connection',function(client){
  console.log('client connected')
  client.on('data',function(data){
    console.log(data)
  })
}) 

服务器确实输出'client connected'但是没有对client.on()部分做任何事情,我找不到另一种方法让服务器监听来自客户端的消息。有没有办法使用tls模块,以便我可以使客户端和服务器根据它们发送和接收的消息进行交互?同样,我不想使用浏览器。

2 个答案:

答案 0 :(得分:0)

@robertklep的评论帮助我解决了我的问题。删除服务器端的socket.pipe(socket)行,在客户端只需使用socket.write()向服务器发送消息。这可以由服务器端的socket.on('data')实例接收。此外,要与多个客户端进行交互,您可以编写如下内容:

var socket = {}; 

const server = tls.createServer(options, function(s){
  client=s.getPeerCertificate().subject.CN
  socket[client] = s;
  socket[client].setEncoding('utf8');
  socket[client].write('welcome')

  for (key in socket){
    socket[key].write('new client connected')
  }

  socket[client].on('data',function(data){
    socket[client].write('data received')
  })

答案 1 :(得分:0)

我认为使用Set来通知新连接已建立连接更为合理。如果要添加到集合中的对象必须是唯一的。您也可以只使用socket.server._connectionKey来确定它是什么客户端,而不必费心获得对等证书。

var sockets = new Set();

const server = tls.createServer(options, (socket) => {
  console.log('server connected',
              socket.authorized ? 'authorized' : 'unauthorized');

  var sock_set_len = sockets.size; //get size of sockets set
  var key = socket.server._connectionKey;

  sockets.add(key); //attempt to add socket to connection list

  if(sock_set_len < sockets.size) { //if the socket _connectionKey is unique, it will be added, and will be treated as a new connection here.
    socket.write("you are connected...");
  }

  socket.on('data',function(data){
    socket.write(data);
  })

  socket.on('end', socket.end);
});

在旁注中,我考虑到Apple规定的最新(iOS 13)TLS限制,创建了一个可处理Obj-C iOS套接字的程序包:

https://github.com/eamonwhiter73/IOSObjCWebSockets

我使用Node JS TLS服务器接收连接,这是Node JS文档中echo server示例的变体