前言
P2P(Peer-to-Peer)技术是一种点对点通信技术,通过将网络中的每个节点作为等级平等的节点,每个节点都可以作为服务端或客户端,从而可以实现分布式架构,大大提高了网络的可伸缩性和灵活性。
Deno 是一个新兴的 JavaScript/TypeScript 运行时,旨在为现代 Web 应用程序提供更好的开发体验,它的原生支持 ES6+,并且具有更强大的安全特性。本文将介绍如何在 Deno 中实现 P2P 通信。
运行 Demo
我们先来看一看如何运行一个简单的 P2P 示例。
创建两个节点
首先,我们需要创建至少两个 Deno 进程以模拟两个节点之间的通信。在本地终端窗口中用以下命令创建两个进程:
$ deno run --allow-net server.ts
$ deno run --allow-net client.ts
这里,我们创建了两个进程,一个用于监听客户端连接的服务器进程(server.ts
),一个用于与服务器建立连接的客户端进程(client.ts
)。
简单通信
在服务器进程中,您需要监听指定的端口,并处理从客户端发送的消息。以下是服务器代码的示例:
-- -------------------- ---- ------- ----- -------- - ------------- ----- ---- --- ------------------- -- --------------- ----- -------- ---------------- ---------- - ---------------- ------------- ----- ------ - --- ----------------- ----- ------ - ----- - - ----- ------------------ -- -- -- ----- ------ ----- -------------------------- ---- - ------------- - --- ----- ------ ---- -- --------- - ----------------- -
在客户端进程中,您需要连接到服务器,并发送一些消息。以下是客户端代码:
-- -------------------- ---- ------- ----- ---- - ----- ---------------- ------------------ ----- ------- - --- -------------- ----- ------- - --- -------------- ----- ------------------------------------ ----- ------ - --- ----------------- ----- ------------------ ------------------------------------ -------------
上述代码中,客户端首先连接到服务器,然后发送 hello
消息。服务器端在接收到这条消息并写回之后,客户端读取其中的响应并输出。
在本地窗口中打开两个 Deno 进程时,您应该看到输出如下:
listen on 0.0.0.0:8080 new connection
然后输出如下:
hello
这表示客户端已向服务器发送了消息,并成功接收到了服务器发回的响应消息。
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 节点的示例代码:
const conn = await Deno.dial("tcp", "127.0.0.1:8080"); const buffer = new Uint8Array(1024); const n = await conn.read(buffer); const id = new TextDecoder().decode(buffer.subarray(0, n)); console.log(`Connected to leader with ID ${id}`);
在代码中,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
类,并重用了 ConnectionManager
。start()
方法开始监听连接,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