Unity .Net 2.0 UPNP端口映射
Unity .Net 2.0 UPNP Port Mapping
我最近一直在尝试为我的游戏设置端口映射。这是为了让其中一位玩家成为主持人。为此,我需要播放器打开端口 7777。
如果已有匹配项,它将直接加入。如果它没有找到空的匹配项,它就会简单地匹配一个。如果它没有成功,它会等到有人做出来并加入它。
因此我需要能够使用 UPnP 之类的东西来映射我的端口。我还需要能够捕获错误,以查看是继续创建匹配项还是简单地等待一个匹配项并加入。
我目前正在使用 .NET 2.0 的 Unity 游戏引擎工作。这让我非常有限,因为 Open.NAT 不兼容。我尝试了 Mono.NAT,但无法正常工作。
有没有人对我应该如何处理这个问题有任何建议?使用哪些库,甚至可能为我提供代码片段以帮助我入门。
谢谢,TwoTen。
Edit1:当前的 Mono.NAT 代码如下所示:
private void DeviceFound(object sender, DeviceEventArgs args)
{
Debug.Log("1");
INatDevice device = args.Device;
Debug.Log("2");
Mapping map = new Mapping(Protocol.Tcp, 6699, 6699);
Debug.Log("3");
device.CreatePortMap(map);
Debug.Log("4");
int test = device.GetAllMappings().Length;
Debug.Log(test);
foreach (Mapping portMap in device.GetAllMappings())
{
Debug.Log("5");
Debug.Log(portMap.ToString());
}
}
private void DeviceLost(object sender, DeviceEventArgs args)
{
INatDevice device = args.Device;
Mapping map = new Mapping(Protocol.Tcp, 6699, 6699);
device.DeletePortMap(map);
}
I 最后调用的调试语句是 4。I 端口没有打开,也没有抛出异常。
我做错了什么?
此外,在我的启动函数中,我调用这个:
NatUtility.DeviceFound += DeviceFound;
NatUtility.DeviceLost += DeviceLost;
NatUtility.StartDiscovery();
我找到了如何成功的答案。我放弃了 Mono.NAT,而是使用 Open.NAT,它已移植到与 Unity 兼容的 .NET 3.5!
我最终使用的最终代码如下所示:
private static Task Test()
{
var nat = new NatDiscoverer();
var cts = new CancellationTokenSource();
cts.CancelAfter(5000);
NatDevice device = null;
var sb = new StringBuilder();
IPAddress ip = null;
return nat.DiscoverDeviceAsync(PortMapper.Upnp, cts)
.ContinueWith(task =>
{
device = task.Result;
return device.GetExternalIPAsync();
})
.Unwrap()
.ContinueWith(task =>
{
ip = task.Result;
sb.AppendFormat("\nYour IP: {0}", ip);
return device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 7777, 7777, 0, "myGame Server (TCP)"));
})
.Unwrap()
.ContinueWith(task =>
{
return device.CreatePortMapAsync(
new Mapping(Protocol.Udp, 7777, 7777, 0, "myGame Server (UDP)"));
})
.Unwrap()
.ContinueWith(task =>
{
sb.AppendFormat("\nAdded mapping: {0}:1700 -> 127.0.0.1:1600\n", ip);
sb.AppendFormat("\n+------+-------------------------------+--------------------------------+------------------------------------+-------------------------+");
sb.AppendFormat("\n| PORT | PUBLIC (Reacheable) | PRIVATE (Your computer) | Description | |");
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
sb.AppendFormat("\n| | IP Address | Port | IP Address | Port | | Expires |");
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
return device.GetAllMappingsAsync();
})
.Unwrap()
.ContinueWith(task =>
{
foreach (var mapping in task.Result)
{
sb.AppendFormat("\n| {5} | {0,-20} | {1,6} | {2,-21} | {3,6} | {4,-35}|{6,25}|",
ip, mapping.PublicPort, mapping.PrivateIP, mapping.PrivatePort, mapping.Description,
mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP", mapping.Expiration.ToLocalTime());
}
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
sb.AppendFormat("\n[Removing TCP mapping] {0}:1700 -> 127.0.0.1:1600", ip);
return device.DeletePortMapAsync(new Mapping(Protocol.Tcp, 1600, 1700));
})
.Unwrap()
.ContinueWith(task =>
{
sb.AppendFormat("\n[Done]");
Debug.Log(sb.ToString());
});
}
我所要做的就是在启动函数中执行此操作:
Test().Wait();
路由器注册端口并打开。然而。网站 canyouseeme.org 出于某种原因未能将端口视为打开状态。为了验证它是否已注册,我进入路由器设置并查找 UPnP。然后有一个应用程序列表,包括我的。我还没有进行真实世界的测试,但一旦完成,我会更新 post。
在此处找到与 Unity 兼容的 Open.NAT 版本:
编辑:我现在已经进行了真实世界的测试。一切正常,用户可以在没有中继和/或统一配对服务器的情况下进行连接
我最近一直在尝试为我的游戏设置端口映射。这是为了让其中一位玩家成为主持人。为此,我需要播放器打开端口 7777。
如果已有匹配项,它将直接加入。如果它没有找到空的匹配项,它就会简单地匹配一个。如果它没有成功,它会等到有人做出来并加入它。
因此我需要能够使用 UPnP 之类的东西来映射我的端口。我还需要能够捕获错误,以查看是继续创建匹配项还是简单地等待一个匹配项并加入。
我目前正在使用 .NET 2.0 的 Unity 游戏引擎工作。这让我非常有限,因为 Open.NAT 不兼容。我尝试了 Mono.NAT,但无法正常工作。
有没有人对我应该如何处理这个问题有任何建议?使用哪些库,甚至可能为我提供代码片段以帮助我入门。
谢谢,TwoTen。
Edit1:当前的 Mono.NAT 代码如下所示:
private void DeviceFound(object sender, DeviceEventArgs args)
{
Debug.Log("1");
INatDevice device = args.Device;
Debug.Log("2");
Mapping map = new Mapping(Protocol.Tcp, 6699, 6699);
Debug.Log("3");
device.CreatePortMap(map);
Debug.Log("4");
int test = device.GetAllMappings().Length;
Debug.Log(test);
foreach (Mapping portMap in device.GetAllMappings())
{
Debug.Log("5");
Debug.Log(portMap.ToString());
}
}
private void DeviceLost(object sender, DeviceEventArgs args)
{
INatDevice device = args.Device;
Mapping map = new Mapping(Protocol.Tcp, 6699, 6699);
device.DeletePortMap(map);
}
I 最后调用的调试语句是 4。I 端口没有打开,也没有抛出异常。 我做错了什么?
此外,在我的启动函数中,我调用这个:
NatUtility.DeviceFound += DeviceFound;
NatUtility.DeviceLost += DeviceLost;
NatUtility.StartDiscovery();
我找到了如何成功的答案。我放弃了 Mono.NAT,而是使用 Open.NAT,它已移植到与 Unity 兼容的 .NET 3.5!
我最终使用的最终代码如下所示:
private static Task Test()
{
var nat = new NatDiscoverer();
var cts = new CancellationTokenSource();
cts.CancelAfter(5000);
NatDevice device = null;
var sb = new StringBuilder();
IPAddress ip = null;
return nat.DiscoverDeviceAsync(PortMapper.Upnp, cts)
.ContinueWith(task =>
{
device = task.Result;
return device.GetExternalIPAsync();
})
.Unwrap()
.ContinueWith(task =>
{
ip = task.Result;
sb.AppendFormat("\nYour IP: {0}", ip);
return device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 7777, 7777, 0, "myGame Server (TCP)"));
})
.Unwrap()
.ContinueWith(task =>
{
return device.CreatePortMapAsync(
new Mapping(Protocol.Udp, 7777, 7777, 0, "myGame Server (UDP)"));
})
.Unwrap()
.ContinueWith(task =>
{
sb.AppendFormat("\nAdded mapping: {0}:1700 -> 127.0.0.1:1600\n", ip);
sb.AppendFormat("\n+------+-------------------------------+--------------------------------+------------------------------------+-------------------------+");
sb.AppendFormat("\n| PORT | PUBLIC (Reacheable) | PRIVATE (Your computer) | Description | |");
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
sb.AppendFormat("\n| | IP Address | Port | IP Address | Port | | Expires |");
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
return device.GetAllMappingsAsync();
})
.Unwrap()
.ContinueWith(task =>
{
foreach (var mapping in task.Result)
{
sb.AppendFormat("\n| {5} | {0,-20} | {1,6} | {2,-21} | {3,6} | {4,-35}|{6,25}|",
ip, mapping.PublicPort, mapping.PrivateIP, mapping.PrivatePort, mapping.Description,
mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP", mapping.Expiration.ToLocalTime());
}
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
sb.AppendFormat("\n[Removing TCP mapping] {0}:1700 -> 127.0.0.1:1600", ip);
return device.DeletePortMapAsync(new Mapping(Protocol.Tcp, 1600, 1700));
})
.Unwrap()
.ContinueWith(task =>
{
sb.AppendFormat("\n[Done]");
Debug.Log(sb.ToString());
});
}
我所要做的就是在启动函数中执行此操作:
Test().Wait();
路由器注册端口并打开。然而。网站 canyouseeme.org 出于某种原因未能将端口视为打开状态。为了验证它是否已注册,我进入路由器设置并查找 UPnP。然后有一个应用程序列表,包括我的。我还没有进行真实世界的测试,但一旦完成,我会更新 post。
在此处找到与 Unity 兼容的 Open.NAT 版本:
编辑:我现在已经进行了真实世界的测试。一切正常,用户可以在没有中继和/或统一配对服务器的情况下进行连接