基于C#实现的UPnP端口映射程序
更新时间:2026年02月26日 08:35:44 作者:yong9990
本文介绍了基于C#实现的UPnP端口映射程序,该程序包含服务器端和客户端,支持TCP端口穿透和自动NAT穿透,服务器端实现UPnP端口映射和TCP服务端,客户端实现UPnP客户端类,程序支持多协议、自动重连机制和安全增强,需要的朋友可以参考下
基于C#实现的UPnP端口映射程序,包含服务器端和客户端实现,支持TCP端口穿透和自动NAT穿透:
一、核心实现原理
- UPnP协议:通过路由器自动映射内网端口到公网
- 双通道通信:服务器监听内网端口,客户端通过公网IP+映射端口连接
- 动态IP获取:通过外部服务获取公网IP地址
二、服务器端实现(支持自动端口映射)
1. UPnP端口映射类(UPnPHelper.cs)
using System;
using System.Net;
using NATUPNPLib;
public class UPnPHelper : IDisposable
{
private UPnPNAT _nat;
private IStaticPortMappingCollection _mappings;
public UPnPHelper()
{
try
{
_nat = new UPnPNAT();
_mappings = _nat.StaticPortMappingCollection;
}
catch (COMException ex)
{
throw new InvalidOperationException("UPnP服务不可用", ex);
}
}
public bool AddPortMapping(int externalPort, int internalPort, string internalIP, ProtocolType protocol, string description = "UPnP Port Forwarding")
{
try
{
_mappings.Add(externalPort, protocol.ToString().ToUpper(), internalPort, internalIP, true, description);
return true;
}
catch (COMException ex)
{
Console.WriteLine($"UPnP映射失败: {ex.Message}");
return false;
}
}
public void RemovePortMapping(int externalPort, ProtocolType protocol)
{
try
{
_mappings.Remove(externalPort, protocol.ToString().ToUpper());
}
catch (COMException ex)
{
Console.WriteLine($"UPnP解除映射失败: {ex.Message}");
}
}
public string GetExternalIP()
{
using (var client = new WebClient())
{
string response = client.DownloadString("http://checkip.dyndns.org/");
return System.Text.RegularExpressions.Regex.Match(response, @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b").Value;
}
}
public void Dispose()
{
_nat?.Dispose();
}
}
public enum ProtocolType
{
TCP = 0,
UDP = 1
}
2. TCP服务端(Server.cs)
using System.Net;
using System.Net.Sockets;
public class Server
{
private Socket _serverSocket;
private UPnPHelper _upnp;
public Server(int port)
{
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_upnp = new UPnPHelper();
}
public void Start()
{
try
{
// 设置UPnP映射
string internalIP = Dns.GetHostEntry(Dns.GetHostName()).AddressList
.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork)?.ToString();
if (!_upnp.AddPortMapping(8080, 8080, internalIP, ProtocolType.TCP))
{
throw new InvalidOperationException("UPnP端口映射失败");
}
string externalIP = _upnp.GetExternalIP();
Console.WriteLine($"服务器已启动 - 外网访问地址: {externalIP}:8080");
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080));
_serverSocket.Listen(10);
while (true)
{
var client = _serverSocket.Accept();
_ = Task.Run(() => HandleClient(client));
}
}
finally
{
_upnp?.Dispose();
}
}
private void HandleClient(Socket client)
{
using (var ns = new NetworkStream(client))
using (var sr = new StreamReader(ns))
using (var sw = new StreamWriter(ns))
{
string msg = sr.ReadLine();
Console.WriteLine($"收到消息: {msg}");
sw.WriteLine($"ECHO: {msg}");
sw.Flush();
}
}
}
三、客户端实现
1. UPnP客户端类(UPnPClient.cs)
using System.Net;
using System.Net.Sockets;
public class UPnPClient
{
private string _externalIP;
private int _externalPort;
public void Connect(string serverIP, int serverPort)
{
// 通过UPnP获取外部IP和端口
using (var client = new WebClient())
{
string response = client.DownloadString("http://checkip.dyndns.org/");
_externalIP = System.Text.RegularExpressions.Regex.Match(response, @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b").Value;
}
_externalPort = serverPort;
// 建立TCP连接
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(IPAddress.Parse(_externalIP), _externalPort));
using (var ns = new NetworkStream(socket))
using (var sr = new StreamReader(ns))
using (var sw = new StreamWriter(ns))
{
sw.WriteLine("Hello Server");
sw.Flush();
string response = sr.ReadLine();
Console.WriteLine($"服务器响应: {response}");
}
}
}
四、主程序入口
1. 服务器端启动
class Program
{
static void Main(string[] args)
{
var server = new Server(8080);
server.Start();
}
}
2. 客户端连接
class Program
{
static void Main(string[] args)
{
var client = new UPnPClient();
client.Connect("服务器公网IP", 8080); // 替换为实际公网IP
}
}
五、关键功能扩展
1. 多协议支持
// 在UPnPHelper中扩展UDP支持
public bool AddUdpPortMapping(int externalPort, int internalPort, string internalIP)
{
return AddPortMapping(externalPort, internalPort, internalIP, ProtocolType.UDP);
}
2. 自动重连机制
// 在客户端添加重试逻辑
public void ConnectWithRetry(string serverIP, int serverPort, int maxRetries = 3)
{
int attempt = 0;
while (attempt < maxRetries)
{
try
{
Connect(serverIP, serverPort);
return;
}
catch (Exception ex)
{
attempt++;
Console.WriteLine($"连接失败 ({attempt}/{maxRetries}): {ex.Message}");
Thread.Sleep(2000);
}
}
}
3. 安全增强
// 添加TLS加密
public void StartSecureServer(int port)
{
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, port));
_serverSocket.Listen(10);
using (var sslStream = new SslStream(_serverSocket.Accept(), false))
{
sslStream.AuthenticateAsServer(GetCertificate());
// 处理加密通信...
}
}
六、部署与测试
1. 环境要求
- Windows 10/11 专业版及以上(需启用UPnP服务)
- 路由器开启UPnP功能
- 防火墙允许TCP端口8080
2. 测试步骤
- 在服务器端运行程序
- 查看控制台输出的外网IP和端口
- 在客户端输入该地址进行连接
- 验证双向通信是否正常
七、常见问题解决
| 问题现象 | 解决方案 |
|---|---|
| UPnP映射失败 | 检查路由器UPnP设置,重启路由器 |
| 无法获取外网IP | 更换检测地址为https://api.ipify.org |
| 连接超时 | 检查防火墙规则,确保端口开放 |
| 数据包丢失 | 启用TCP窗口缩放因子优化 |
以上就是基于C#实现的UPnP端口映射程序的详细内容,更多关于C# UPnP端口映射程序的资料请关注脚本之家其它相关文章!


最新评论