目標:實現兩個只有內網IP地址的直接通信(不需要經過服務器的中轉)
關鍵字:
1。NAT(網絡地址解析):內網的主機向公網的服務器發送數據時,路由會利用NAT機制將內網的地址解析成公網的地址。
2。Session(會話):一個會話是由內部IpEndPoint和目的公網IpEndPoint組成的,在第一個udp包被髮送出去的時候創建.
如下:如果client想向server發送一個udp數據包,在server看來client是Nath後的IpEndPoint:221.65.14.32:4000,這時Session記錄了192.168.0.10:7000和60.65.54.41:5000
這樣在server向221.65.14.32:4000發送數據時Nat會利用Session將數據發送到192.168.0.10:7000
------------| client |----------| Nat |-------------| server |
------------192.168.0.10:7000--------->221.65.14.32:4000------------>60.65.54.41:5000
實現udp打洞:
前提:在一段時間內,內部主機利用相同的端口向不同服務器發送UDP數據包時Nat端會分配相同的端口
也 就是說利用192.168.0.10:7000依次向server1:60.65.54.41:5000和server2:60.65.54.41: 5200發送udp數據包時,從server1和server2來看client的地址都是221.65.14.32:4000。
Server端代碼:
UdpClient secondUdp = new UdpClient(7200);
IPEndPoint remote=new IPEndPoint(IPAddress.Any,0);
while (true)
{
firstUdp.Receive(ref remote);
Console.WriteLine("First Udp Packet Come From:{0}",remote.ToString());
secondUdp.Receive(ref remote);
Console.WriteLine("First Udp Packet Come From:{0}",remote.ToString());
Console.WriteLine("===========================");
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UdpTestClient
{
class Program
{
static void Main(string[] args)
{
IPAddress addr =IPAddress.Parse("221.198.110.220");
UdpClient client = new UdpClient();
byte[] bytes=System.Text.Encoding.ASCII.GetBytes("fasdf");
client.Send(bytes,bytes.Length,new IPEndPoint(addr,7100));
Console.WriteLine("Just Wait five seconds...");
System.Threading.Thread.Sleep(5000);
client.Send(bytes, bytes.Length, new IPEndPoint(addr, 7200));
}
}
}