我最近一直在尝试为我的游戏设置端口映射。这是为了让其中一名球员成为主持人。为此,我需要播放器打开端口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);
}
我调用的最后一个调试语句是数字4.我没有打开端口,也没有抛出任何异常。 我做错了什么?
另外,在我的开始功能中,我称之为:
NatUtility.DeviceFound += DeviceFound;
NatUtility.DeviceLost += DeviceLost;
NatUtility.StartDiscovery();
答案 0 :(得分:1)
我找到了如何成功的答案。我放弃了Mono.NAT,转而使用已移植到.NET 3.5的Open.NAT,它与Unity兼容!
我最终使用的最终代码如下所示:
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。然后有一个包括我的应用程序列表。我还没有做真实世界的测试,但是一旦完成,我会更新帖子。
在这里可以找到与Unity兼容的Open.NAT版本:
编辑:我现在已经进行了真实世界的测试。一切正常,用户可以在没有中继和/或联合配对服务器的情况下进行连接