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();
        }
    }
}

 

 

 有问题欢迎大家联系我

 

posted @ 2015-11-03 14:11  VisionaryMan‪  阅读(2804)  评论(1编辑  收藏  举报