p2p tcp nat 原理图+源码(原创)

现今网上p2p的 udp nat穿透 文章 多如牛毛, p2p tcp nat的文章寥寥无几 ,up主研究了几天 终于有所收获,特来向大家分享,请大家多多支持!

1、首先你要有台外网服务器 或者 电信的运营商 支持转发的路由器(具体过程不多说,请自行百度)

2、一台能上网的电脑(内网里面的电脑 不然没有意义)

核心代码就是:

socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
作用就是让已经连接的端口可以再次监听 从而实现tcp nat 的目的

原理图:

p2p tcp nat 原理图+源码(原创)

外网服务器端代码 (ps:up主穷 买不起服务器 只能用公司的路由器转发 ,请见谅!):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading; namespace TcpNatTestS
{
class Program
{ public static IPAddress GetLocalIP()
{
try
{
string HostName = Dns.GetHostName(); //得到主机名
IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
for (int i = ; i < IpEntry.AddressList.Length; i++)
{
//从IP地址列表中筛选出IPv4类型的IP地址
//AddressFamily.InterNetwork表示此IP为IPv4,
//AddressFamily.InterNetworkV6表示此地址为IPv6类型
if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
{
return IpEntry.AddressList[i];
}
}
return IPAddress.Any;
}
catch (Exception ex)
{
return IPAddress.Any;
}
} static void Main(string[] args)
{
TcpListener tcp = new TcpListener(new IPEndPoint(GetLocalIP(), ));
tcp.Start();
new Thread(e =>
{
while (true)
{
var lianjie = tcp.AcceptTcpClient();
//new TcpClient().Connect((IPEndPoint)lianjie.Client.RemoteEndPoint);
lianjie.Client.Send(UnicodeEncoding.Unicode.GetBytes("你的外网ip是:" + lianjie.Client.RemoteEndPoint));
Console.WriteLine("内网服务器: 本地端口:" + lianjie.Client.LocalEndPoint + "远程端口:" + lianjie.Client.RemoteEndPoint);
}
}).Start();
Console.ReadKey();
}
}
}

内网客户端(你需要自己填写外网服务器ip):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading; namespace TcpNatTestA
{
class Program
{
public static IPAddress GetLocalIP()
{
try
{
string HostName = Dns.GetHostName(); //得到主机名
IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
for (int i = ; i < IpEntry.AddressList.Length; i++)
{
//从IP地址列表中筛选出IPv4类型的IP地址
//AddressFamily.InterNetwork表示此IP为IPv4,
//AddressFamily.InterNetworkV6表示此地址为IPv6类型
if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
{
return IpEntry.AddressList[i];
}
}
return IPAddress.Any;
}
catch (Exception ex)
{
return IPAddress.Any;
}
}
static void Main(string[] args)
{
new Thread(e =>
{
TcpClient clinet = new TcpClient();
clinet.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
var bendi = new IPEndPoint(GetLocalIP(), );
clinet.Client.Bind(bendi);
clinet.Connect(new IPEndPoint(IPAddress.Parse("请填写你的服务器ip"), ));
TcpListener tcp = new TcpListener(bendi);
tcp.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
tcp.Start();
new Thread(() =>
{
while (true)
{
var jiqi= tcp.AcceptTcpClient();
Console.WriteLine("内网客户机: 本地端点:" + bendi + " 远程端点:" + jiqi.Client.RemoteEndPoint);
}
}).Start();
clinet.Client.Send(UnicodeEncoding.Unicode.GetBytes("呵呵呵呵"));
byte[] hh = new byte[];
var weishu = clinet.Client.Receive(hh);
byte[] temp = new byte[weishu];
Array.Copy(hh, temp, weishu);
//Console.WriteLine("远程端口:"+clinet.Client.RemoteEndPoint);
Console.WriteLine(UnicodeEncoding.Unicode.GetString(temp));
}).Start();
Console.ReadKey();
}
}
}

有问题欢迎大家联系我

上一篇:ECMAScript5之Array


下一篇:Java 给 PowerPoint 文档添加背景颜色和背景图片