1

我想建立一个 P2P 配对服务器。情况如下:

  • 我在 NAT'd 路由器后面有 2 个以上的对等方。
  • 我在静态 IP 上的端口转发路由器后面有一台服务器。
  • 服务器的工作是注册每个对等点的联系信息,并在请求时将其发送给任何其他对等点。
  • 然后,对等点可以向服务器查询其他人的列表,并直接连接到他们。

目前,对等点可以连接到服务器,注册他们的地址,并查询其他对等点的地址。我的问题是互相介绍同行。

我目前正在像这样获取每个对等方的内部和外部 IP 地址。它主要基于 Lidgren 附带的主服务器示例;但是,这只是将用户连接到客户端/服务器会话,而我需要点对点。

//client code; getting our internal IP and sending it to the server
NetOutgoingMessage om = server_client.CreateMessage(); //create message on the server's connection
... //header
IPAddress mask;
var endpoint = new IPEndPoint(NetUtility.GetMyAddress(out mask), peer_client.Port); //gets the internal IP address
... //write message data and send to server

当服务器收到请求时,或者当对等点注册到服务器时,它会从连接消息中获取该对等点的外部 IP。然后,在处理请求时,我们可以从两个对等方访问两个 IP:

//server code, handling the peer request message:
...
string key = msg.ReadString();
Output("Requesting peer: " + key);

IPEndPoint requester_internal = msg.ReadIPEndPoint();
IPEndPoint requester_external = msg.SenderEndPoint;

//attempt to find requested user
User u = null;
if (Users.TryGetValue(id, out u))
{
    IPEndPoint target_internal = u.IPInternal;
    IPEndPoint target_external = u.IPExternal;
    ...
    //send the requested IPs to the sender, and the sender's IPs to the target.
}

现在,问题是如何使用此信息(或建立连接所需的任何其他信息)将对等点相互连接,因为其他基础设施已经运行。

我的第一次尝试是使用内置的 Introduce 方法:

//server code, continuing from the above
//instead of directly sending IPs to users, introduce them ourselves
s_server.Introduce(target_internal, target_external, requester_internal, requester_external, key);

这似乎在某种程度上起作用,但它连接到每个客户端上的服务器连接而不是对连接,并且只在发送方上成功。

尝试手动连接发送的 IP 会导致无休止的“尝试连接”消息:

//peer code; handling 'other peer data received' msg
IPEndPoint peer_internal = msg.ReadIPEndPoint();
IPEndPoint peer_external = msg.ReadIPEndPoint();

Output("SERVER: Recieved peer IP. Attempting to connect to:\n" + peer_internal.ToString() + "\n" + peer_external.ToString());

NetOutgoingMessage om = peer_client.CreateMessage();
om.Write((Int32)3); //unique header for debugging purposes

peer_client.Connect(peer_external, om); //tried both internal and external, no dice

最后,我看到的 IP 示例是从服务器转储的:

P1 Internal: 169.xxx.xxx.xxx:14243 //local subnet address, using the proper port
P1 External: xxx.xxx.xxx.xxx:62105 //IP address of the system, matching that from any IP testing site, but using a seemingly random port
P2 Internal: 169.xxx.xxx.xxx:14243 //same as above for the second peer
P2 External: xxx.xxx.xxx.xxx:62106

我认为问题在于对等连接的外部端口是沿线路某处随机创建的,而不是使用我在创建它时指定的端口。因此,它不能提前转发。我会很高兴用户被要求转发特定端口,因为许多 P2P 游戏都是这样工作的。

换句话说,我似乎拥有使 NAT 穿孔正常工作所需的一切,但我缺乏 Lidgren 的知识来实现​​它。

最后,这是我设置 peer_client 的方式:

//peer code: initialize the connection to any other peers we may connect to later
NetPeerConfiguration pconfig = new NetPeerConfiguration(appidstr_client);
pconfig.Port = 14243; //properly forwarded in router
pconfig.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
pconfig.SetMessageTypeEnabled(NetIncomingMessageType.UnconnectedData, true);
pconfig.AcceptIncomingConnections = true;
peer_client = new NetPeer(pconfig);
peer_client.Start();
4

1 回答 1

1

您是否使用“config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);”启用了介绍消息?

“14243”是错字吗?在示例中,主服务器侦听 14343,客户端侦听 14242。

“这似乎在某种程度上有效,但它连接到每个客户端上的服务器连接而不是对等连接,并且只在发送者上成功。” 我不明白这是什么意思。如果您使用的是 NetPeer 类,则没有特定的“服务器连接”?

请记住 IPEndPoint 包含端口号,以防您将其存储在某个地方,您可能希望将其设置为您尝试打开的端口。

于 2014-07-19T08:00:12.980 回答