避免在P2P网络架构中同时进行双向连接

时间:2019-03-15 17:01:58

标签: c sockets networking p2p gio

好吧,我是一位认证的程序员,多年来从事各种各样的工作,但是我最终将要提出一个关于我完全无法解决的问题的问题。我希望Stack Overflow能够在这么多年后再次拯救我的生命。


这是关于唯一对问题。我正在使用GIO的GSocketClientGSocketService高级API建立异步连接并接受两个对等点之间的传入连接(显然,每个连接都使用相同的程序)。由于对等端可以同时彼此连接,因此这导致2个连接,而只需要一个。

我尝试了很多事情,包括删除绑定IP地址先于另一个IP连接的连接(这样一个连接就被丢弃了),但这仍然无法正常工作,所以我的脑袋现在开始旋转什么位置和优先位置。

为了不使事情变得过于复杂,我要直截了当地问:在这种情况下正确的方法是什么?

1 个答案:

答案 0 :(得分:2)

这很艰难,但是经过三天的不断思考和测试,我找到了解决方案。

我坚信这个问题不应该被否决(特别是因为它看起来似乎“自命不凡”),但是我们不能总是获得最好的S / O。

问题

两个对等要同时连接时 将有两个连接,而只需要一个。 接受,连接和处理时甚至更加复杂 是异步的,可以随时发生 对等体分别使用相同的程序,因此是相当严格的P2P体系结构。 这是拜占庭将军问题的经典示例,它是最困难的计算机问题之一。

解决方案

该解决方案不涉及完全同步,因此它缺乏进行异步连接,接受和处理的要点,并且在处理之后不需要删除连接。此有效解决方案背后有3个主要思想。

  1. 某种类型的记录(我使用GList)包含“待处理”的IPs
  2. 将IP转换为数字的功能
  3. 等待并授予权限的系统

如果正确实现并在正确的地方使用,就可以了。现在更多细节。

某种包含“待定” 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)仅适用于其中一个同伴。

等待和授予权限的系统

连接必须等待接受线程的许可。尽管该呼叫必须处于阻塞状态,但不会造成任何开销,在大多数情况下,它将立即返回。 在收到许可(被拒绝(1)或被授予(2))之后,如果它发送ACK(3),则返回(1-丢弃连接)或继续。主机等待ACK,然后以相同的方式返回(断开连接)或继续(如果授予许可)。

主持人应根据排他性标准确定是拒绝还是授予。 首先,它将检查挂起的连接列表中是否存在IP(基本上意味着该程序也尝试连接),如果存在,则检查IP条件是否匹配,否则发送授予或拒绝。


重要的是,在connect的sync调用中,在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 */