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

11

有一个演示向我展示了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聊天服务器。非常感谢您的帮助!我认为将此示例添加到网站中也会很有用。

2个回答

9
使用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
谢谢,我很感激!这已经接近我的解决方案了 :) - Félix Poulin-Bélanger

4

好的,经过一番尝试后,这是我制作的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的方式。实际上,我不太确定在Node中socket.on('data')事件代表什么;似乎只是来自TCP流的任意长度的数据。


1
在node.js中,socket.on('data')表示操作系统在TCP套接字上提供的任何数据。TCP是一个流,因此实际到达的数据块完全是随意的。它受许多因素的影响,包括发送方式和传输方式,但没有人控制它。因此,在TCP套接字上到达的数据是任意的数据块,无论平台或环境如何,除非您有更高级别的代码来解析数据并将其转换为具有语义含义的特定数据块(例如消息、行等)。 - jfriend00

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接