C#点对点编程(最好是去中心化)

4
我正在编写一个应用程序,用于分享内容。您有一个“同行”列表。选择其中一些人,您就可以开始共享内容(文本和二进制数据)。在局域网中,如果输入其他人的IP地址,则通信可以进行。
我有几个问题:
1. 是否有某种模式可用于编写此类聊天应用程序,以便发现谁在线和谁不在线(本地和互联网上都是如此)?我知道可以通过连接到所有集中式服务器来完成,但是分散式的情况怎么办,特别是当您在LAN上时?
2. 连接到在线客户端时,它们大多没有IP地址,而是被防火墙等东西所包围,显然IP地址不是机器的IP地址,而且某些端口将被阻止。有什么解决方法?
附言:我已经阅读了许多与此相关的stackoverflow页面。有些人说可以,有些人说不行。有些甚至提供了有关C#比特流客户端和服务器的信息。只要我能在.NET中完成,我非常愿意听取建议。(C#,F#,VB都可以)
非常感谢任何建议。

通常每个实例都会宣布自己。你可以尝试找到其他实例,但首先需要知道它们的IP地址和端口。这可以在没有中央服务器的情况下完成,但是您需要一个常见对等点列表,其中一个对等点必须始终处于开启状态(轮流使用,不一定是同一个对等点)。 - GeoffM
  1. 如果端口被阻止,你无能为力。那个节点必须进行端口转发和开放端口。出于安全原因,从外部进行此操作是不可取的 - 或者如果可以的话,要使用一些高质量的安全机制来进行操作。除此之外,你似乎在问“是否可能”(是的,受到上述限制的影响)而不是“我该如何做这件事”(没有足够的信息)。
- GeoffM
那么,在客户端是本地但具有动态IP地址的情况下,或者当客户端不在同一局域网但通常跨越互联网时,我该怎么办呢?在这种情况下,他们的IP地址可能是未知的。 - ritcoder
如果你无法广播(例如互联网),并且事先不知道他们的地址,那么除非他们在某个地方公布了自己的地址,否则就无法知道他们的位置。你需要一个已知的中心位置来查找这些地址,或者像我之前说的那样,需要一个分散的已知共同对等体集合。 - GeoffM
2个回答

1

发现意味着一个端点必须能够找到其他端点。在局域网上,如果允许网络层的广播(UDP),那么这是可行的。一个典型的场景是 SNMP 管理器广播一个 SNMP GET 消息,并查看同一网络中有多少个 SNMP 代理响应。这是分散式的,因为没有中央登记点存储所有终端点列表。

然而,超出局域网意味着没有像广播那样轻松地找到其他端点的方法。那么就需要一个集中式的解决方案。

因此,请进一步总结您的应用程序在所有层面(应用程序、网络等)中的情况,以查看是否存在分散式的解决方案。另外,当您在其他地方阅读他人的结论时,也应注意他/她提到的特殊情况。这些结论可能仅适用于那些情况。


1
我明白从互联网上来看,你肯定需要一个中央服务器。假设我有一个网站(http://registration.mydomain.com),客户可以通过互联网访问它,那么如果没有中央服务器,我需要什么才能让他们进行通信? - ritcoder
一旦所有客户端在中央服务器上注册了自己的IP地址和打开的端口,这些信息就可以在它们之间共享。然后,它们中的每一个都可以初始化与另一个客户端的直接连接(当然需要仔细处理NAT)。 - Lex Li
好的。所以如果我理解正确,客户端连接到中央服务器并捕获其IP和端口。如果这样做了,他们就可以获取有关该想法的信息。我的困惑在于IP地址可能不是机器的直接IP地址。您能详细说明NATting部分吗? - ritcoder
它被称为“洞穴打洞”,http://en.wikipedia.org/wiki/NAT_hole_punching。如果您在应用程序内实现这样的机制,那么它们可以在某种程度上摆脱限制。 - Lex Li

0
如果您想要一个中央服务器(registration.mydomain.com),则可以采用以下解决方案: 1. 同行使用“我在这里,这是我的详细信息”消息连接到中央服务器。 2. 服务器记录同行的IP地址和端口。 3. 同行从服务器请求其他同行的列表。 4. 同行使用提供的列表直接连接到其他同行。
每个同行都应向服务器发送更新以指示它们是否仍然存在-或者服务器可以偶尔尝试连接每个同行(不是所有Web服务器都能做到)以确定信息本身。
每个同行还应定期向服务器请求更多的同行,以防有任何连接或断开连接,尽管后者在广播时可能会注意到您的套接字。

1
那应该在一般情况下可以工作。然而,大多数情况下,节点可能没有自己的IP地址,而是使用连接到互联网的路由器的IP地址。在这种情况下,同一路由器后面的所有节点将显示为具有相同的IP地址。这该如何解决? - ritcoder
你有点进入“新问题”领域了。但是,无论某个东西连接的位置在哪里,都会有一个端口号。将其与IP地址相关联使用即可。 - GeoffM

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