你的位置:首页 > ASP.net教程

[ASP.net教程]p2p tcp nat 原理图+源码(原创)


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

 

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

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

 

核心代码就是:

socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);


作用就是让已经连接的端口可以再次监听 从而实现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 = 0; 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(), 8085));      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 = 0; 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(), 7896);        clinet.Client.Bind(bendi);        clinet.Connect(new IPEndPoint(IPAddress.Parse("请填写你的服务器ip"), 8085));        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[500];        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();    }  }}

 

 

 有问题欢迎大家联系我