【问题标题】:How to write a TCP chat server with Deno?如何用 Deno 编写 TCP 聊天服务器?
【发布时间】:2020-09-02 12:32:59
【问题描述】:

真正让我相信 Node 的强大功能的演示之一是 Ryan Dahl 在此视频中展示的简单 TCP 聊天服务器:https://www.youtube.com/watch?v=jo_B4LTHi3I&t=28m23s

演示中的代码如下所示:

const net = require('net');
const server = net.createServer();

const sockets = [];

server.on('connection', (socket) => {
  sockets.push(socket);

  socket.on('data', (message) => {
    for (const current_socket of sockets) {
      if (current_socket !== socket) {
        current_socket.write(message);
      }
    }
  });

  socket.on('end', () => {
    const index = sockets.indexOf(socket);
    sockets.splice(index, 1);
  });
});

server.listen(8000, () => console.log('tcp server listening on port 8000'));

我在 Deno 网站上找到的唯一 TCP 示例是一个如下所示的回显服务器:

const listener = Deno.listen({ port: 8080 });
console.log("listening on 0.0.0.0:8080");
for await (const conn of listener) {
  Deno.copy(conn, conn);
}

它很好而且很紧凑,但是我一直无法使用Deno.Connreadwrite 方法将这个例子变成一个TCP 聊天服务器。任何帮助将非常感激!我也认为这将是一个有用的示例添加到网站。

【问题讨论】:

    标签: javascript node.js tcp chat deno


    【解决方案1】:

    使用Deno.listen 创建服务器并使用Deno.connect 连接到该服务器。

    tcp 服务器/客户端的一个简单示例是:

    server.js

    const encoder = new TextEncoder();
    const decoder = new TextDecoder();
    
    const listener = Deno.listen({ port: 8080 });
    
    console.log("listening on 0.0.0.0:8080");
    for await (const conn of listener) {
      // Read message
      const buf = new Uint8Array(1024);
      await conn.read(buf);
      console.log('Server - received:', decoder.decode(buf))
      // Respond
      await conn.write(encoder.encode('pong'))
      conn.close();
    }
    

    client.js

    const encoder = new TextEncoder();
    const decoder = new TextDecoder();
    
    const conn = await Deno.connect({ hostname: "127.0.0.1", port: 8080 })
    // Write to the server
    await conn.write(encoder.encode('ping'));
    // Read response
    const buf = new Uint8Array(1024);
    await conn.read(buf);
    console.log('Client - Response:', decoder.decode(buf))
    conn.close();
    
    

    您可以从这里构建。例如,对于聊天服务器,您将保持连接打开,并发送多条消息。

    【讨论】:

    • 谢谢,非常感谢!这接近我的解决方案:)
    【解决方案2】:

    好吧,玩多了,这里是我的 TCP 聊天服务器:

    const server = Deno.listen({ port: 8000 });
    console.log("tcp server listening on port 8000");
    
    const connections: Deno.Conn[] = [];
    
    for await (const connection of server) {
      // new connection
      connections.push(connection);
      handle_connection(connection);
    }
    
    async function handle_connection(connection: Deno.Conn) {
      let buffer = new Uint8Array(1024);
      while (true) {
        const count = await connection.read(buffer);
        if (!count) {
          // connection closed
          const index = connections.indexOf(connection);
          connections.splice(index, 1);
          break;
        } else {
          // message received
          let message = buffer.subarray(0, count);
          for (const current_connection of connections) {
            if (current_connection !== connection) {
              await current_connection.write(message);
            }
          }
        }
      }
    }
    

    代码看起来与 Node 版本完全不同。也就是说,TCP 不维护消息边界,而 Deno 版本通过读入 Uint8Array 缓冲区来明确这一点。这类似于 Rust 的 std::nettokio::net 模块处理 TCP。实际上,我不太确定 socket.on('data') 事件在 Node 中代表什么;它似乎只是来自 TCP 流的任意长度的数据。

    【讨论】:

    • socket.on('data') in node.js 表示操作系统在该 TCP 套接字上提供的任何数据。 TCP 是一个流,所以实际数据到达哪个块是完全任意的。它受到很多事情的影响,包括它是如何发送的以及两者之间的传输,但不受任何人控制。因此,数据以任意数据块的形式到达 TCP 套接字,无论平台或环境如何,除非您有更高级别的代码来解析数据并将其转换为具有语义意义的特定数据块(例如消息、行等...)。
    猜你喜欢
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 2011-08-05
    • 2016-10-02
    • 1970-01-01
    • 2018-11-19
    • 1970-01-01
    • 2019-04-01
    相关资源
    最近更新 更多