【问题标题】:SOCKET.IO - console.log is printing desired output but not io.emitSOCKET.IO - console.log 正在打印所需的输出,但不是 io.emit
【发布时间】:2021-02-13 18:09:20
【问题描述】:

我正在使用 socket.io 将命令行的输出流式传输到 html 网页。

服务器:

  var app = require('express')();
    var http = require('http').createServer(app);
    var io = require('socket.io')(http);
    const { spawn } = require("child_process");
    const ls = spawn("mycommand", ['-l 500'], {shell: true});
    
    app.get('/', (req, res) => {
      res.sendFile(__dirname + '/index.html');
    });
    
    
    
    io.on('connection', (socket) => {
      socket.on('chat message', (msg) => {
        ls.stdout.on("data", data => {
        io.emit(`${data}`, msg);
    });
      });
    });
    
    
    http.listen(3000, () => {
      console.log('listening on *:3000');
    });

客户:

<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: 0.5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>



<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
  $(function () {
    var socket = io();
    $('form').submit(function(e){
      e.preventDefault(); // prevents page reloading
      socket.emit('chat message', $('#m').val());
      $('#m').val('');
      return false;
    });
    socket.on('chat message', function(msg){
      $('#messages').append($('<li>').text(msg));
    });
  });
</script>


  </body>
</html>

在我的服务器代码中使用 io.emit() 时,我没有在 HTML 页面上获得输出,但如果我改为使用 console.log() 所需的输出打印在我的命令控制台上,但不在 HTML 上。不允许我在 HTML 上显示输出的错误在哪里?

我的目标是当用户向服务器提交消息时,服务器将输出从命令行流式传输到客户端。

【问题讨论】:

  • 您的声明 io.emit(`${data}`, msg); 将发出一个消息名称,该名称根据 data 的值而变化,您的客户端将没有侦听器,因此它永远不会看到该消息。客户端代码仅显示 chat message 的侦听器,因此如果您希望该客户端代码接收您的消息,则必须发送 io.emit('chat message', data),但我不完全确定您正在尝试做什么。
  • 当客户端执行此操作时,您希望服务器对您发送的$('#m').val() 做什么也不清楚:socket.emit('chat message', $('#m').val());
  • 这个服务器代码也有一个问题,每次收到chat message 消息时,它都会在此处添加另一个侦听器:ls.stdout.on("data", data =&gt; { ...});,这将导致这些侦听器累积并复制处理程序到位这会产生问题。
  • 此外,您的服务器代码会在服务器启动时发出 spawn 命令,最初没有在其上放置任何侦听器,然后再也不会与它通信。除非它不断地喷出数据,否则不清楚客户端如何在正确的时间开始从它那里获取数据,并且为该客户端附加的侦听器永远不会被删除。这不可能是正确的。
  • 我没有在这里写答案,因为我可以看到一堆错误的东西,但我不知道你实际上想通过生成的过程完成什么,所以我不知道推荐什么代码。我不清楚这段代码的预期目标。

标签: javascript html node.js websocket socket.io


【解决方案1】:

根据您的 cmets,您可以在收到如下聊天消息时代表某个特定客户端开始收听流:

io.on('connection', (socket) => {
  socket.on('chat message', (msg) => {
    function listener(data) {
        // send data from ls back to cilent
        socket.emit('lsdata', data);
    }
    ls.stdout.on('data', listener);
  });
  // when socket disconnects, remove the listener
  socket.on('disconnect', () => {
    ls.stdout.off('data', listener);
  });
});

那么,客户端代码需要一个lsdata事件的监听器:

socket.on('lsdata', function(msg){
  $('#messages').append($('<li>').text(msg));
});

请注意,这里还有很多您不清楚的要求,因为这会开始侦听任何聊天消息,并且如果它从同一个客户端接收到多条聊天消息,则会创建重复的侦听器(这似乎不对 - 但不清楚你希望它如何工作)。看起来更像是客户端应该发送一个'startListening' 消息,然后如果它想从数据流中拔出它可以发送一个'stopListening' 消息。

【讨论】:

  • 我想避免创建重复的侦听器。您能否说明如何与客户端发送“startListening”/“stopListening”消息?
  • @MeditaInc. - 您只需在 socket.io 上从客户端向服务器发送startListening 消息,然后开始在该消息上侦听ls 进程,而不是在chat message 进程上。同样,您可以(如果需要)从客户端向服务器发送stopListening 消息,并停止监听该消息上的ls 进程。然后,当您的客户发送 chat message 时,您可以对该消息执行任何其他操作。
猜你喜欢
  • 1970-01-01
  • 2021-07-21
  • 2015-04-21
  • 1970-01-01
  • 2014-08-08
  • 2015-08-23
  • 1970-01-01
  • 2018-06-30
  • 1970-01-01
相关资源
最近更新 更多