【发布时间】:2020-07-11 05:11:31
【问题描述】:
我正在尝试直接连接(使用 TCP)实现 NAT 的路由器后面的两个设备。如我所见,路由器正在转换我设备的端口号,因此我的计算机上的端口 13000(我的应用程序正在侦听传入 TCP 连接的端口)将具有与公开看到的完全不同的值。为了连接两个设备,我需要知道监听器的“公共端口号”是什么。
我创建了公开可用的“集合服务器”。首先,我在客户端 A 和服务器之间创建了 TCP 连接。服务器提取端口号并将其传递给其他客户端,以便他们可以尝试连接到客户端 A。但我意识到,当我与服务器创建新的 Tcp 连接时,我的应用程序会创建新的端口来发送数据包。因此,服务器提取新创建的端口的公共端口,仅用于连接到该服务器,而不是我的侦听器的公共端口。
所以我正在尝试以其他方式解决它。这个想法是:我正在发送源端口设置为 TcpListener 端口的 UDP 数据包。这样,理论上,服务器可以从 TcpListener 的传入消息公共端口中提取(通过从 UDP 数据报中获取源端口)并将其传递给我网络中的其他设备。
// client side
public void AdvertiseListener(IPAddress address, int port, Guid localDeviceId)
{
UdpClient client = new UdpClient(ListenerPort); // changing datagram source to port of my TcpListener
IPEndPoint remoteEP = new IPEndPoint(address, port);
_logger.LogInformation($"Advertising Tcp port to server at {address.MapToIPv4().ToString()}:{port}");
byte[] data = localDeviceId.ToByteArray();
for (int a = 0; a < 10; a++)
{
client.Send(data, data.Length, remoteEP);
}
}
// server side
public void AdvertisementsHandler()
{
AdvertisementListener = new UdpClient(ListenerPort);
AdvertisementListener.BeginReceive(new AsyncCallback(HandleAdverticement), null);
}
private void HandleAdverticement(IAsyncResult ar)
{
IPEndPoint senderIpEndPoint = new IPEndPoint(0, 0); // source address of incoming datagram
var receivedData = AdvertisementListener.EndReceive(ar, ref senderIpEndPoint);
[...]
_logger.LogInformation($"ADVERTICEMENT RECEIVED, port is {senderIpEndPoint.Port}");
try
{
AdvertisementListener.BeginReceive(new AsyncCallback(HandleAdverticement), null);
}
catch (Exception e)
{
_logger.LogError("Advertiser failed");
}
}
问题是:我的服务器由于某种原因收到未翻译的号码。 HandleAdverticement 中的 senderIpEndPoint 等于 13000,这是我的私有端口号。具有讽刺意味的是,我的路由器似乎这次离开了端口。你有什么想法可以改变什么来解决我的问题吗?
【问题讨论】:
-
有什么原因不能在路由器上使用端口转发?
-
@PatrickMcvay 是的,我希望我的应用在我无法访问路由器设置的网络上运行。
-
我相信你已经想到了这一点,但是你是否尝试过使用套接字而不是 UdpClient 呢?文档docs.microsoft.com/en-us/dotnet/framework/network-programming/…
标签: c# sockets network-programming tcpclient tcplistener