是否需要将socket.io服务器附加到http服务器?

时间:2019-09-27 13:31:35

标签: node.js websocket

我是第一次学习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,我可以运行每项服务而无需彼此接触

2 个答案:

答案 0 :(得分:1)

WebSocket协议是一个单独的协议,它不是建立在HTTP之上的。但是,HTTP协议本身具有升级机制(即WebSocket握手),可以将简单的HTTP连接转换为WebSocket连接。而且由于浏览器使用该浏览器,因此如果没有HTTP,就不可能通过浏览器建立WebSocket连接。

附带说明: socket.io确实也利用了其他协议。如果WebSocket协议不可用,它会退回给他们。

现在,以下(显然)是一种观点:无需将一台服务器连接到另一台服务器。实际上,这是一种反模式。通常,您希望组件尽可能独立,以使对一个组件的更改不会影响另一个组件。而且:即使两者都通过HTTP运行,也没有理由这样做。我发现这些教程至少具有误导性。

答案 1 :(得分:0)

我添加了有关smtp服务器的概念证明,该服务器只是捕获所有收到的邮件,但不发送到真实目标。

此外,它在socket.io连接上发出事件。

全部不使用http服务器。

SMTP + socket.js服务器

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);

VUE.JS示例代码

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>

如何使用pm2继续运行smtp / socket服务器和vue-cli dev服务器应用的示例

将此称为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

运行