C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# UPnP端口映射程序

基于C#实现的UPnP端口映射程序

作者:yong9990

本文介绍了基于C#实现的UPnP端口映射程序,该程序包含服务器端和客户端,支持TCP端口穿透和自动NAT穿透,服务器端实现UPnP端口映射和TCP服务端,客户端实现UPnP客户端类,程序支持多协议、自动重连机制和安全增强,需要的朋友可以参考下

基于C#实现的UPnP端口映射程序,包含服务器端和客户端实现,支持TCP端口穿透和自动NAT穿透:

一、核心实现原理

  1. UPnP协议:通过路由器自动映射内网端口到公网
  2. 双通道通信:服务器监听内网端口,客户端通过公网IP+映射端口连接
  3. 动态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. 环境要求

2. 测试步骤

  1. 在服务器端运行程序
  2. 查看控制台输出的外网IP和端口
  3. 在客户端输入该地址进行连接
  4. 验证双向通信是否正常

七、常见问题解决

问题现象解决方案
UPnP映射失败检查路由器UPnP设置,重启路由器
无法获取外网IP更换检测地址为https://api.ipify.org
连接超时检查防火墙规则,确保端口开放
数据包丢失启用TCP窗口缩放因子优化

以上就是基于C#实现的UPnP端口映射程序的详细内容,更多关于C# UPnP端口映射程序的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文