現今網上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(); } } }
有問題歡迎大家聯系我