如何使用Deno编写TCP聊天服务器?

时间:2020-05-16 16:47:23

标签: javascript node.js tcp chat deno

让我深信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.Conn的{​​{1}}和read方法将本示例转换为TCP聊天服务器。任何帮助将非常感激!我还认为添加到网站将是一个有用的示例。

2 个答案:

答案 0 :(得分:2)

使用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();

您可以从此处构建。对于聊天服务器,您将保持连接打开状态,并发送多条消息。

答案 1 :(得分: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流的任意长度的数据。