我希望使用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模块,以便我可以使客户端和服务器根据它们发送和接收的消息进行交互?同样,我不想使用浏览器。
答案 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
示例的变体