简体   繁体   English

从服务器连接Lidgren中的对等节点

[英]Connecting peers in Lidgren from a server

I would like to set up a P2P matchmaking server. 我想设置一个P2P对接服务器。 The situation is as follows: 情况如下:

  • I have 2+ peers behind NAT'd router(s). 我在NAT路由器后面有2个以上的对等节点。
  • I have a server behind a port-forwarded router on a static IP. 我在静态IP上的端口转发路由器后面有一台服务器。
  • The server's job is to register the contact information of each peer, and send it any other peer when requested. 服务器的工作是注册每个对等方的联系信息,并在请求时将其发送给其他任何对等方。
  • A peer could then query the server for a list of others, and directly connect to them. 然后,对等方可以向服务器查询其他列表,然后直接连接到它们。

Presently, peers can connect to the server, register their addresses, and query it for other peers' addresses. 当前,对等方可以连接到服务器,注册其地址并向其查询其他对等方的地址。 My issue is introducing the peers to each other. 我的问题是互相介绍同行。

I am presently getting the internal and external IP addresses of each peer like so. 我现在正在像这样获取每个对等方的内部和外部IP地址。 It is heavily based around the Master Server Sample that ships with Lidgren; 它很大程度上基于Lidgren随附的主服务器示例。 however, that merely connects users to client/server sessions, while I require peer to peer. 但是,这仅将用户连接到客户端/服务器会话,而我需要点对点。

//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

When the server gets a request, or when a peer is registered to the server, it gets that peer's external IP from the connection message. 当服务器收到请求或对等方注册到服务器时,它将从连接消息中获取该对等方的外部IP。 We then have access to both IPs from both peers when handling a request: 然后,当处理请求时,我们可以从两个对等方访问两个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.
}

Now, the issue is how to connect the peers to each other using this information (or, whatever other information is required to make the connection), since the other infrastructure is already functional. 现在,问题在于如何使用此信息(或进行连接所需的任何其他信息)将对等方彼此连接,因为其他基础结构已经在起作用。

My first attempt was using the built-in Introduce method: 我的第一次尝试是使用内置的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);

This seemed to work to some degree, but it connected to the server connection on each client instead of the peer connection, and only succeeded on the sender. 这似乎在某种程度上可行,但是它连接到每个客户端上的服务器连接,而不是对连接,并且仅在发送者上成功。

Attempting to manually connect with the sent IPs resulted in endless "attempting to connect" messages: 尝试手动与发送的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

Lastly, a sample case of the IPs that I'm seeing, as dumped from the server: 最后,从服务器转储的我看到的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

I believe that the issue is that the peer connection's external port is randomly created somewhere along the line, instead of using that which I specify when creating it. 我认为问题在于对等连接的外部端口是沿着线路随机创建的,而不是使用我在创建时指定的端口。 As such, it can't be forwarded in advance. 因此,它无法提前转发。 I would be happy with users being required to forward a specific port, as many P2P games work this way. 我很高兴要求用户转发特定的端口,因为许多P2P游戏都以这种方式工作。

In other words, I seem to have everything that I need in order to get NAT punching working properly, but I lack the knowledge of Lidgren to make it happen. 换句话说,我似乎拥有使NAT打孔正常工作所需的一切,但是我缺乏Lidgren的知识来实现​​它。

Finally, here is how I set up my peer_client: 最后,这是我设置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();

Did you enable introduction messages using "config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);"? 您是否使用“ config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);”启用了简介消息?

Is "14243" a typo? 是“ 14243”有错字吗? In the sample the master server listens on 14343 and the clients listen on 14242. 在示例中,主服务器侦听14343,客户端侦听14242。

"This seemed to work to some degree, but it connected to the server connection on each client instead of the peer connection, and only succeeded on the sender." “这似乎在某种程度上可行,但是它连接到每个客户端上的服务器连接,而不是对等连接,并且仅在发送者上成功。” I don't understand what this means. 我不明白这是什么意思。 If you're using the NetPeer class there's no specific "server connection"? 如果您使用的是NetPeer类,那么没有特定的“服务器连接”吗?

Remember IPEndPoint includes the port number, in case you're storing it away somewhere you might want to set it to the port you're trying to punch open. 请记住,IPEndPoint包含端口号,以防万一您将其存储在某个地方时,可能需要将其设置为要打孔的端口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM