我想在C#中实现TCP打洞(NAT穿透)。如果需要,可以通过会合服务器来完成。我找到了http://sharpstunt.codeplex.com/,但无法让其工作。理想情况下,我需要一种方法,将端口号(int)作为参数传递给该方法,调用该方法后该端口在NAT上可用(“端口转发”)。如果该方法只返回在NAT上可用的某些端口号,也是可以的。有人在C#中完成过这个吗?您能给我一些关于sharpstunt或其他东西的工作示例吗?
我想在C#中实现TCP打洞(NAT穿透)。如果需要,可以通过会合服务器来完成。我找到了http://sharpstunt.codeplex.com/,但无法让其工作。理想情况下,我需要一种方法,将端口号(int)作为参数传递给该方法,调用该方法后该端口在NAT上可用(“端口转发”)。如果该方法只返回在NAT上可用的某些端口号,也是可以的。有人在C#中完成过这个吗?您能给我一些关于sharpstunt或其他东西的工作示例吗?
var discoverer = new NatDiscoverer();
var device = await discoverer.DiscoverDeviceAsync();
await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1600, 1700, "The mapping name"));
var sb = new StringBuilder();
var ip = await device.GetExternalIPAsync();
sb.AppendFormat("\nAdded mapping: {0}:1700 -> 127.0.0.1:1600\n", ip);
sb.AppendFormat("\n+------+-------------------------------+--------------------------------+------------------------------------+-------------------------+");
sb.AppendFormat("\n| PROT | PUBLIC (Reacheable) | PRIVATE (Your computer) | Descriptopn | |");
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
sb.AppendFormat("\n| | IP Address | Port | IP Address | Port | | Expires |");
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
foreach (var mapping in await device.GetAllMappingsAsync())
{
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+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
Console.WriteLine(sb.ToString());
此外,MSDN上还有一篇关于NAT穿透的博客文章:https://blogs.msdn.microsoft.com/ncl/2009/07/27/end-to-end-connectivity-with-nat-traversal/
http://sipsorcery.codeplex.com有一个可用的STUN服务器。
SipSorcery.core -> SipSorcery.Net -> Stun
听起来你可能把TCP和UDP搞混了。TCP是一种面向连接的协议,防火墙和路由器很容易理解,需要一个发起者(客户端)和一个监听者(服务器)。如果客户端和服务器都在防火墙或NAT后面,你不能打洞而不让它们两个连接到某个代理服务器(该服务器没有防火墙)。这样做的问题是代理将负责中继它们所有的流量。
从你的问题来看,似乎你更感兴趣的是UDP打洞,它利用了UDP是无状态且非面向连接的特点。因此,大多数状态跟踪防火墙会对UDP数据流进行“最佳猜测”,并假定离开给定端口的流量将在同一端口接收回复,并自动路由它们回来。如果使用某些非通道手段(例如仅传递地址而不是数据的TCP服务器),两个对等方都可以在相同的端口上相互传输数据,则它们各自的防火墙/NAT路由器将打开允许流量进入的洞口。
至于如何实现,这完全取决于你将如何将对等方的IP地址传递给彼此。一旦你拥有它,只需在约定的端口上开始传输UDP数据包,并等待回复即可。