gpt4 book ai didi

sockets - 如何进行 TCP 打洞?

转载 作者:可可西里 更新时间:2023-11-01 02:30:38 26 4
gpt4 key购买 nike

问题如下。这是我当前没有成功的测试代码。

static void Main(string[] args)
{
if (args.Count() != 3)
{
Console.WriteLine("Bad args");
}
var ep = new IPEndPoint(IPAddress.Parse(args[0]), int.Parse(args[1]));
var lp = new IPEndPoint(IPAddress.Any, int.Parse(args[2]));

var s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
s.Bind(lp);

var c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
c.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
c.Bind(lp);

Task.Run(() => { try { c.Connect(ep); } catch { } });
s.Listen(10);
var v = s.Accept();
v.Close();
}

如何进行 TCP 打洞?我正在使用远程服务器进行测试。我正在运行 wget local_public_ip:port/test。我为端口 80 设置了路由器,因此不需要打洞。我的代码得到了连接。现在我在其他端口上尝试,但我无法确切地弄清楚如何打洞。

我所做的是(C#代码)

var l = new TcpListener(8090);
l.Start();
try { var o = new TcpClient(); o.Connect("myserverip", 123); }
catch(Exception ex) {}
var e = l.AcceptSocket();
Console.WriteLine(e.RemoteEndPoint.AddressFamily);

我想也许我需要在 out tcp 连接上设置本地端点。

TcpClient(new System.Net.IPEndPoint(new System.Net.IPAddress(bytearray), port));

我犯了一个错误,得到了这个异常

The requested address is not valid in its context

将字节数组固定为 192,168,1,5 它似乎可以正确进行传出连接。现在我已经使用我的监听端口与远程 IP 建立了输出连接,我认为 wget 能够连接到我。不是这样的

如何进行 TCP 打洞?

最佳答案

我会使用 http://www.bford.info/pub/net/p2pnat/index.html 中详述的“顺序打洞技术” .执行同时连接和套接字重用似乎要简单得多。打洞没有必要完全同时做任何事情(无论如何,这在分布式系统中是一个毫无意义的概念)。

我已经实现了打洞。我的路由器似乎不喜欢它。 Wireshark 显示出站打洞 SYN 正确,但对方打不通。我使用 TcpView.exe 验证所有端口并禁用所有防火墙。应该是路由器问题。 (这是一个奇怪的侵入性路由器。)

class HolePunchingTest
{
IPEndPoint localEndPoint;
IPEndPoint remoteEndPoint;
bool useParallelAlgorithm;

public static void Run()
{
var ipHostEntry = Dns.GetHostEntry("REMOTE_HOST");

new HolePunchingTest()
{
localEndPoint = new IPEndPoint(IPAddress.Parse("LOCAL_IP"), 1234),
remoteEndPoint = new IPEndPoint(ipHostEntry.AddressList.First().Address, 1235),
useParallelAlgorithm = true,
}.RunImpl();
}

void RunImpl()
{
if (useParallelAlgorithm)
{
Parallel.Invoke(() =>
{
while (true)
{
PunchHole();
}
},
() => RunServer());
}
else
{

PunchHole();

RunServer();
}
}

void PunchHole()
{
Console.WriteLine("Punching hole...");

using (var punchSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
EnableReuseAddress(punchSocket);

punchSocket.Bind(localEndPoint);
try
{
punchSocket.Connect(remoteEndPoint);
Debug.Assert(false);
}
catch (SocketException socketException)
{
Console.WriteLine("Punching hole: " + socketException.SocketErrorCode);
Debug.Assert(socketException.SocketErrorCode == SocketError.TimedOut || socketException.SocketErrorCode == SocketError.ConnectionRefused);
}
}

Console.WriteLine("Hole punch completed.");
}

void RunServer()
{
using (var listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
EnableReuseAddress(listeningSocket);

listeningSocket.Bind(localEndPoint);
listeningSocket.Listen(0);

while (true)
{
var connectionSocket = listeningSocket.Accept();
Task.Run(() => ProcessConnection(connectionSocket));
}
}
}

void ProcessConnection(Socket connectionSocket)
{
Console.WriteLine("Socket accepted.");

using (connectionSocket)
{
connectionSocket.Shutdown(SocketShutdown.Both);
}

Console.WriteLine("Socket shut down.");
}

void EnableReuseAddress(Socket socket)
{
if (useParallelAlgorithm)
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
}
}

您可以为 useParallelAlgorithm 尝试这两个值。两者都应该有效。

此代码用于服务器。它在本地 NAT 中打了一个洞。然后,您可以使用任何允许选择本地端口的客户端从远程端进行连接。我使用了 curl.exe。显然,Windows 上的 telnet 不支持绑定(bind)到端口。 wget 显然两者都不是。

使用 TcpView 或 Process Explorer 验证两端的端口是否正确。您可以使用 Wireshark 来验证数据包。设置过滤器,例如 tcp.port = 1234

当你“呼唤”打一个洞时,你启用了元组(你的IP,你的端口,远程IP,远程端口)进行通信。这意味着所有进一步的通信都必须使用这些值。所有套接字(入站或出站)都必须使用这些确切的端口号。如果您不知道:传出连接也可以控制本地端口。这并不常见。

关于sockets - 如何进行 TCP 打洞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26694286/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com