Deno 中如何实现 p2p 通信?

阅读时长 12 分钟读完

前言

P2P(Peer-to-Peer)技术是一种点对点通信技术,通过将网络中的每个节点作为等级平等的节点,每个节点都可以作为服务端或客户端,从而可以实现分布式架构,大大提高了网络的可伸缩性和灵活性。

Deno 是一个新兴的 JavaScript/TypeScript 运行时,旨在为现代 Web 应用程序提供更好的开发体验,它的原生支持 ES6+,并且具有更强大的安全特性。本文将介绍如何在 Deno 中实现 P2P 通信。

运行 Demo

我们先来看一看如何运行一个简单的 P2P 示例。

创建两个节点

首先,我们需要创建至少两个 Deno 进程以模拟两个节点之间的通信。在本地终端窗口中用以下命令创建两个进程:

这里,我们创建了两个进程,一个用于监听客户端连接的服务器进程(server.ts),一个用于与服务器建立连接的客户端进程(client.ts)。

简单通信

在服务器进程中,您需要监听指定的端口,并处理从客户端发送的消息。以下是服务器代码的示例:

-- -------------------- ---- -------
----- -------- - ------------- ----- ---- ---
------------------- -- ---------------

----- -------- ---------------- ---------- -
  ---------------- -------------
  ----- ------ - --- -----------------
  ----- ------ -
    ----- - - ----- ------------------
    -- -- -- ----- ------
    ----- -------------------------- ----
  -
  -------------
-

--- ----- ------ ---- -- --------- -
  -----------------
-

在客户端进程中,您需要连接到服务器,并发送一些消息。以下是客户端代码:

-- -------------------- ---- -------
----- ---- - ----- ---------------- ------------------
----- ------- - --- --------------
----- ------- - --- --------------

----- ------------------------------------
----- ------ - --- -----------------
----- ------------------
------------------------------------
-------------

上述代码中,客户端首先连接到服务器,然后发送 hello 消息。服务器端在接收到这条消息并写回之后,客户端读取其中的响应并输出。

在本地窗口中打开两个 Deno 进程时,您应该看到输出如下:

然后输出如下:

这表示客户端已向服务器发送了消息,并成功接收到了服务器发回的响应消息。

P2P 通信

与简单通信不同的是,我们需要在多个 Deno 进程之间建立 P2P 连接以进行更加复杂的通信。P2P 通信可以通过多个节点之间互相建立连接来实现,这需要某种中心化节点(例如服务器)来进行连接管理。

建立连接

首先,我们需要定义连接管理器来管理 Node 之间的连接。连接管理器应该将一个节点标识为“leader”节点,它应该负责管理所有其他节点之间的连接。以下是连接管理器的示例代码:

-- -------------------- ---- -------
----- ----------------- -
  ------------- ----------- - ---

  ------------------ -------- -------- ------- --

  ----- ---------------- ------- -
    ----- ---- - ----- ---------------- ---------
    -----------------------------
    ---------------------- -- -------------
  -

  ----- -------- -
    ----- -------- - ------------- ----- ---- ---
    --- ----- ------ ---- -- --------- -
      -----------------------------
      ---------------- ---------- ---- ---------------------
    -
  -

  ----- ------------------ ------- -
    ----- ------- - --- --------------
    ----- ------ - ------------------------
    --- ------ ---- -- ------------------ -
      --- -
        ----- -------------------
      - ----- --- -
        -------------------------
        ----------------- - ---------------------------- -- - --- ------
      -
    -
  -

  ----- ------- -
    --- ------ ---- -- ------------------ -
      ----- -------------
    -
  -
-

在代码中,connect() 方法建立 P2P 连接到指定地址的其他 Deno 进程,并在连接成功时存储连接。listen() 方法在当前 Deno 进程的端口上监听并等待新的 P2P 连接。broadcast() 方法广播消息到所有已知的连接。close() 方法则用于断开所有连接。

在这个例子中,我们假定 Port 8080 是客户端使用的默认端口。

实现 Leader 节点和 Peer 节点

现在我们已经定义了 P2P 连接管理器,我们可以通过创建 Leader 和 Peer 类来使用它创建 P2P 网络。

Leader 节点应该是一个带有所有其他 Peer 节点信息的中心节点。在这里,我们将为所有连接到 Leader 节点的 Peer 节点分配随机 ID。以下是 Leader 节点的示例代码:

-- -------------------- ---- -------
----- ----------------- - --- ----------------------------------
----- ---------------------------

----- ------ - ----- -------- --------- - - ---

----- -------- ---------------- ---------- -
  ---------------- ---------- ---- ---------------------
  ----- -- - ----------------------------------------
  --------- - -----
  ----- -------------- --------------------------
-

--- ----- ------ ---- -- ------------------ -
  -----------------
-

在代码中,Leader 创建了一个 connectionManager,并使用之前定义的 listen() 方法开始监听连接请求。然后,Leader 监听所有传入连接,并为新连接分配 ID。每个连接都将存储在全局 peers 对象中,其中 ID 是键,连接是值。

像这样使用 Math.random() 函数生成 ID 不是最好的方法,但它在这里可以很好地工作。在生产环境中,您应该使用更可靠的方法来生成唯一的 UUID。

Peer 节点应该连接到 Leader 节点,并等待其分配的 ID。以下是 Peer 节点的示例代码:

在代码中,Peer 首先连接到 Leader,然后等待 Leader 分配一个随机 ID。连接的 ID 将通过网络连接发送,我们等待其传输完毕并打印连接的 ID。

实现 P2P 通信

现在我们已经定义了 Leader 和 Peer 类,我们可以使用 ConnectionManager 和 Peer 和 Leader 类来实现 P2P 通信。

以下是向 ConnectionManager 中添加消息广播功能的 Peer 类:

-- -------------------- ---- -------
----- ---- -
  ------- -------- ------------------ ------------------
  ------- -------------- -------

  ------------------------------ ------------------ -
    ---------------------- - ------------------
  -

  ----- ---------------- ------- -
    ----- ----------------------------------------
    ---------------------- -- -------------
  -

  ----- ------- -
    ----- ---- - ----- ---------------- ------------------
    ----- ------ - --- -----------------
    ----- - - ----- ------------------
    ----------------- - --- --------------------------------------- ----
    ---------------------- -- ------ ---- -- -----------------------
  -

  ----- ------------------ ------- -
    ----- ---------------------------------
      ---------------------- --------------
    --
  -

  ----- ------- -
    ----- -------------------------------
  -
-

在代码中,connect() 方法创建 P2P 连接到指定地址。start() 方法连接到 Leader,并等待分配的 Peer ID。broadcast() 方法广播一个带有对等节点 ID 的消息。close() 方法用于关闭连接。

以下是向 ConnectionManager 中添加消息广播功能的 Leader 类:

-- -------------------- ---- -------
----- ------ -
  ------- -------- ------------------ ------------------

  ------------------------------ ------------------ -
    ---------------------- - ------------------
  -

  ----- ------- -
    ----- --------------------------------
    ------------------- -- ------------------------------------
  -

  ----- ------------------ ------- -
    ----- ----------------------------------------- ---------------
  -

  ----- ------- -
    ----- -------------------------------
  -
-

在代码中,我们定义了一个 Leader 类,并重用了 ConnectionManagerstart() 方法开始监听连接,broadcast() 方法广播带有 Leader ID 的消息,close() 方法用于关闭连接。

我们已经定义了 P2P 通信的通用类,现在我们可以创建 Leader 和 Peer 的示例对象并开始测试。以下是使用 Leader 和 Peer 对象创建 P2P 通信的示例:

-- -------------------- ---- -------
----- ----------------- - --- ----------------------------------

----- -------------
  --- ----------------------------------
  ------ -- -- -
    ----- ---- - --- ------------------------
    ----- -------------
    ----- -------------------------------
    ----- ------------------ ---------
  -----
---

在代码中,我们创建了一个 ConnectionManager 对象,并向其中添加一个 Leader 和一个 Peer 异步启动。

Peer 节点首先启动并连接到 Leader。接下来,它向 ConnectionManager 连接至 127.0.0.1:8080,并发送一条 Hi there! 消息。

现在,我们已经在 Deno 中实现了 P2P 通信。请记住,在使用 Deno 进行 P2P 通信时必须使用 --allow-net 权限进行触发,这允许向指定的主机地址和端口上传输数据。

总结

本文介绍了如何在 Deno 中实现 P2P 通信。我们用 ConnectionManager 类模拟一组节点,用 Peer 和 Leader 类实现 P2P 通信。我们还介绍了如何使用 Deno 提供的安全特性以及如何使用 TypeScript 编写类型安全的 Node.js 应用程序。希望这篇文章对于您理解 P2P 通信以及如何在 Deno 中实现 P2P 通信有所帮助。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65a5df35add4f0e0ffe6ef75

纠错
反馈