好吧,我是一名经过认证的程序员,多年来一直在创造各种奇迹,但我终于要就一个我完全无法解决的问题提出一个问题。我希望多年之后 Stack Overflow 能够再次拯救我的生命。
<小时/>这是关于唯一对问题。我正在使用 GIO 的 GSocketClient
和GSocketService
用于在两个对等点之间建立异步连接并接受传入连接的高级 API(显然每个都使用相同的程序)。由于对等点可以同时相互连接,因此这会产生 2 个连接,而实际上只需要一个连接。
我尝试了太多的事情,包括删除绑定(bind)IP号在另一个之前的连接(以便一个连接被丢弃),但这仍然并不总是有效,所以我现在开始思考什么和哪里应该首先出现。
为了不让我尝试过的所有事情变得过于复杂,我会直接问:在这种情况下正确的方法是什么?
最佳答案
这很困难,但经过 3 天的坚持思考和测试..我找到了解决方案。
我坚信这个问题不应该被否决(特别是因为它似乎“自命不凡且浮夸”),但我们不能总是充分利用 S/O,不是吗?
问题
当两个对等点想要同时相互连接时 将有两个连接,而实际上只需要一个。 接受、连接、处理时就更复杂了 是异步的,可以随时发生,而且两者都可以 对等体分别使用相同的程序,因此具有相当严格的P2P架构。 这是拜占庭将军问题的典型例子,拜占庭将军问题是最难的计算机问题之一。
解决方案
该解决方案不涉及完全同步,因此缺乏异步连接、接受和处理的要点,并且不需要在处理后删除连接。这个有效的解决方案背后有 3 个主要想法。
- 某种记录(我使用
GList
)来包含“待处理”IP - 将IP转换为数字的函数
- 等待并授予权限的系统
如果正确实现并在正确的地方使用,您就拥有了它。现在有更多细节。
包含“待处理”IP 的某种记录
正如我所说,这可以是一个列表。追加、搜索和删除操作必须由互斥体锁定。从列表中删除 IP 必须在接受时、搜索后和断开连接通知程序中进行。
IP转数字函数
例如rScanf = sscanf(ip, "%u.%u.%u.%u", &bytes[0], &bytes[1], &bytes[2], &bytes[3]);
然后将每个数字相加。这被用作排他性标准。 if(remote_ip_number > local_ip_number)
仅对于其中一个对等方为 true。
等待并授予权限的系统
连接必须等待接受线程的许可。虽然调用必须是阻塞的,但它不会造成任何开销,大多数情况下它会立即返回。 之后,如果它收到许可(拒绝 (1) 或授予 (2)),它会发送 ACK (3) 并返回(1-断开连接)或继续。主机等待 ACK,然后以相同的方式返回(断开连接)或继续(如果授予权限)。
主办方应根据排他性标准决定是否拒绝或同意。 首先,它检查 IP 是否存在于挂起的连接列表中(基本上意味着程序也尝试连接),如果存在,如果 IP 条件匹配,则发送授予或拒绝。
<小时/>重要的是,在连接的同步调用早期,在实际尝试连接之前,将 IP 添加到挂起连接列表中,并且程序的构建方式必须首先连接到无论它想连接谁,然后托管谁,以便注册第一个待处理的 IP。这在可预测性方面略有优势。
connect(PETER); /* adds PETER ip to listPending */
connect(JOHN); /* adds JOHN ip to listPending */
host(ME); /* Gives permission if IP does not exist in listPending or it does but local ip number < remote ip number */
关于c - 避免 P2P 网络架构中同时双向连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55187491/