我是第一次学习socket.io。 我想启动一个简单的套接字服务器。 我看到在互联网上找到的每个示例都是这样的:
var http = require('http');
var fs = require('fs');
// Loading the index file . html displayed to the client
var server = http.createServer(function(req, res) {
fs.readFile('./index.html', 'utf-8', function(error, content) {
res.writeHead(200, {"Content-Type": "text/html"});
res.end(content);
});
});
// Loading socket.io
var io = require('socket.io').listen(server);
// When a client connects, we note it in the console
io.sockets.on('connection', function (socket) {
console.log('A client is connected!');
});
server.listen(8080);
我的问题的核心很简单:在所有此类示例中,我都看到io侦听附加到现有http服务器的信息。
这是一个要求吗? 如果是,为什么?是否通过http传输了websocket协议?
我的用例可能有点奇怪:我有一个vue开发服务器,该服务器必须保持运行,因为它提供实时重载等。它正在侦听端口8080,并且由vue-cli-service提供,所以我不能修改它以附加一些东西。
此外,我还有一个“手工制作的”实验性smtp服务器,它是在node.js中制作的,并在端口25上运行
我想使用websocket来允许我的smtp服务器“发布”并且允许我的Vue.js webapp“监听”。
最终目标:使用一个简单的webgui创建一个独立的smtp-catch-all系统,因此通过我的smtp发送的每封邮件都被“推送”到我的webapp中,并且从未存储(也从未真正发送过!)
鉴于此,我想创建一个“独立” socket.io服务器。如果只需要一台http服务器,我将在特定端口上创建第二台服务器,以允许http-> websocket升级。那么我的Web应用将与该辅助服务器上的套接字服务器进行通讯。
我更喜欢这种方式,因为使用pm2,我可以运行每项服务而无需彼此接触
答案 0 :(得分:1)
WebSocket协议是一个单独的协议,它不是建立在HTTP之上的。但是,HTTP协议本身具有升级机制(即WebSocket握手),可以将简单的HTTP连接转换为WebSocket连接。而且由于浏览器使用该浏览器,因此如果没有HTTP,就不可能通过浏览器建立WebSocket连接。
附带说明: socket.io确实也利用了其他协议。如果WebSocket协议不可用,它会退回给他们。
现在,以下(显然)是一种观点:无需将一台服务器连接到另一台服务器。实际上,这是一种反模式。通常,您希望组件尽可能独立,以使对一个组件的更改不会影响另一个组件。而且:即使两者都通过HTTP运行,也没有理由这样做。我发现这些教程至少具有误导性。
答案 1 :(得分:0)
我添加了有关smtp服务器的概念证明,该服务器只是捕获所有收到的邮件,但不发送到真实目标。
此外,它在socket.io连接上发出事件。
全部不使用http服务器。
const SMTPServer = require("smtp-server").SMTPServer;
const io = require('socket.io')(2626);
const server = new SMTPServer({
logger: true,
debug: true,
allowInsecureAuth: true,
onAuth(auth, session, callback) {
console.log("onAuth, user", auth.username, "password", auth.password);
if (auth.username !== "abc" || auth.password !== "def") {
return callback(new Error("Invalid username or password"));
}
io.emit("smtpAuth", auth);
callback(null, { user: 123 }); // where 123 is the user id or similar property
},
onConnect(session, callback) {
console.log("onConnect, from ip ", session.remoteAddress);
io.emit("smtpConnect", session);
return callback(); // Accept the connection
},
onMailFrom(address, session, callback) {
console.log("onMailFrom", address.address);
io.emit("smtpMailFrom", address);
return callback(); // Accept the address
},
onRcptTo(address, session, callback) {
console.log("onRcptTo", address.address);
io.emit("smtpRcptTo", address);
return callback(); // Accept the address
},
onData(stream, session, callback) {
var email_content = "";
// stream.pipe(email_content); // print message to console
stream.on('data', (chunk) => { email_content += chunk });
stream.on("end", function() {
// Stream ended
console.log (email_content);
io.emit("smtpData", email_content);
callback();
});
}
});
server.on("error", err => {
console.log("Error %s", err.message);
});
server.listen(25);
socket.io服务器会在发生新情况时自动通知此组件。 在这种情况下,它可以记录所有事件,但也可以保存整个电子邮件(原始)数据。
<template>
<div class="hello">
<h1>Le email che abbiamo ricevuto per te</h1>
<pre
v-for="(message, index) in messages"
:key="index"
>{{
message
}}</pre>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
messages: [],
}
},
sockets: {
connect() {
console.log('socket connected')
},
smtpAuth(val) {
console.log('SMTP AUTH', val);
},
smtpConnect(val) {
console.log('SMTP CONNECT', val);
},
smtpMailFrom(val) {
console.log('SMTP MAIL FROM', val);
},
smtpRcptTo(val) {
console.log('SMTP RCPT TO', val);
},
smtpData(val) {
console.log('SMYP DATA', val);
this.messages.push(val);
}
},
};
</script>
将此称为ecosystem.config.js
module.exports = {
apps: [
{
name: "WEB",
script: "./node_modules/@vue/cli-service/bin/vue-cli-service.js",
args: "serve"
},
{
watch: true,
name: "SMTP",
script: "./server/index.js"
}
]
};
以pm2 run ecosystem.config.js