用UPnP穿透内网

frombegintoend 原文 用UPnP穿透内网

参考了网上的一篇文章,由于时间长了,具体地址不知道了。

引入了一个DLL: Interop.NATUPNPLib.dll,实现穿透局域网,进行Socket通信。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Text.RegularExpressions;
using System.IO;

using System.Net;
using System.Net.Sockets;
using NATUPNPLib;

namespace _22UPnP穿透内网
{
    class Program
    {
        static void Main(string[] args)
        {
            //获取Host Name
            //-------------------------------------------------------------------------
            string serverName = Dns.GetHostName();
            Console.WriteLine("Server(本机)名称:" + serverName);
            //从当前Host Name解析IP地址,筛选IPv4地址是本机的内网IP地址。
            IPAddress internalIP = Dns.GetHostEntry(serverName).AddressList
                .Where(i => i.AddressFamily == AddressFamily.InterNetwork)
                .FirstOrDefault();
            Console.WriteLine("Server(本机)内网IP:" + internalIP);

            UPnPNAT upnp = new UPnPNAT();
            IStaticPortMappingCollection staticPortMappingCollection = upnp.StaticPortMappingCollection;
            if (staticPortMappingCollection == null)
            {
                Console.WriteLine("没有检测到路由器,或者路由器不支持UPnP功能。");
                return;
            }

            int internalPort = 3898;//Server的端口号
            int externalPort = 4343;//对应映射的外部端口号

            staticPortMappingCollection.Add(
                externalPort,//外网端口
                "TCP",//协议类型
                internalPort,//内网端口
                internalIP.ToString(),//内网IP地址
                true,//是否开启
                "UPNP_Test"//描述
                );

            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            EndPoint serverEndPoint = new IPEndPoint(internalIP, internalPort);
            serverSocket.Bind(serverEndPoint);
            serverSocket.Listen(1);
            Console.WriteLine("开启服务端监听......\n\n");

            Thread serverThread = new Thread(() => {
                Socket socket = null;
                while (true)
                {
                    if (socket!= null || (socket = serverSocket.Accept()) != null)
                    {
                        byte[] byteRec = new byte[1024*1024];//设置消息接收缓存区
                        int msgLen = socket.Receive(byteRec);
                        string msgRec = Encoding.UTF8.GetString(byteRec,0,msgLen);
                        Console.WriteLine("[Server端]\n收到来自Client的消息:\n{0}", msgRec);
                    }
                }
            });
            serverThread.IsBackground = true;
            serverThread.Start();

            // 客户端代码段,完整的实现,需将此代码段修改后,在外网的客户端中运行
            //-------------------------------------------------------------------------
            // 获取外网IP地址;方法1
            string externalIP;//外网IP变量
            externalIP="";
            IPAddress[] IPs = Dns.GetHostAddresses("www.baidu.com");
            foreach (IPAddress ip in IPs)
            {
                Console.WriteLine("获取外网IP成功:" + ip);
                externalIP = ip.ToString();
            }

            // 方法2
            //var regex = @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b";//正则
            //Console.WriteLine("开始获取外网IP......");
            //using (var webclient = new WebClient())
            //{
            //    var rawRes = webclient.DownloadString("https://www.baidu.com/");
            //    externalIP = Regex.Match(rawRes, regex).Value;
            //}
            //externalIP = "111.13.101.208"; // baidu.com
            //Console.WriteLine("获取外网IP成功:" + externalIP);

            externalIP = internalIP.ToString();
            Thread clientThread = new Thread(() =>
            {
                ClientConnectToServer(IPAddress.Parse(externalIP), internalPort);//externalPort,在外网运行时,internalPort处需改为externalPort
            });
            clientThread.Start();
            Console.ReadKey();
        }

        static void ClientConnectToServer(IPAddress remoteIP, int remotePort)
        {
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            clientSocket.Connect(new IPEndPoint(remoteIP, remotePort));
            IPEndPoint remoteEndPoint = clientSocket.RemoteEndPoint as IPEndPoint;
            for (int i = 0; i < 3; i++)
            {
                string msgFromClient = string.Format("Hello, this msg is from Client. \n{2}\n[Remote IP: {0}, Remote Port: {1} ]\n",
                    remoteEndPoint.Address, remoteEndPoint.Port, DateTime.Now
                );
                byte[] bytes = Encoding.UTF8.GetBytes(msgFromClient);
                //客户端向服务端发送消息
                clientSocket.Send(bytes);
                Thread.Sleep(1000);
            }
        }
    }
}

附:源码下载地址(附有Interop.NATUPNPLib.dll): UPnP_to_through_the_intranet(16-12-8_2324).rar

时间: 2024-10-16 13:08:08

用UPnP穿透内网的相关文章

通过VPS穿透内网发布内网服务(未完待续)

当我们有一个本地服务又想暂时对外提供的时候,发现机子在内网.这个时候我们刚好手上有台VPS,那么接下来我们就来尝试下穿透内网对外提供 主机名 IP VPN IP 备注 VPS 外网192.168.31.133 192.168.0.1 外网VPS server 内网192.168.137.2 192.168.0.234 VPN客户端 1.VPS开启VPN,我们选择pptp比较简单. 需要安装ppp pptpd 还需要支持iptables(安装iptables为了做nat,基本都带iptables)

穿透内网所了解的一些知识

动机 内网是相对于外网而言的,内网即是私有网络,互联网上的每个主机必须有一个唯一的IP地址来标识,现有的IPv4的地址为32位,所能标识的主机非常有限,随着internet上主机数量的不断的发展,IPv4地址的短缺越来越明显,IP地址资源也就愈加显得捉襟见肘.为了解决这种问题,出现了一种解决IPv4地址短缺以避免IP地址枯竭的方案,就是我们所谓的NAT(网络地址转换)技术,现在NAT成了家庭和小型办公室网络连接上的路由器的一个标准特征,但是,NAT也让主机之间的通信变得复杂,导致通信效率的降低.

QQ通讯原理及QQ是怎么穿透内网的(转)

QQ是一个基于TCP/UDP协议的通讯软件 发送消息的时候是UDP打洞,登陆的时候使用HTTP~因为登陆服务器其实就是一个HTTP服务器,只不过不是常用的那些,那个服务器是腾讯自行开发的!!! 一.登录 QQ客户端在局域网内,当你打开QQ登录到QQ服务器时,通过外网,你的客户端与QQ服务器建立了一个长连接.你可以用netstat -bn  看到此连接的状态是 establish 此时,在QQ服务器那面看到的连接的IP是你们局域网对外的IP.举个例子:       QQ服务器      IP:12

花生棒2代:穿透内网 让NAS一起去旅行

---恢复内容开始--- 在公网环境下,要实现用域名进行远程访问管家婆管理软件.服务器或门店视频监控等,可用动态域名解析软件.但如今IPV4资源枯竭下,长城宽带等宽带运营商更多的给用户分配了内网IP地址.内网怎么支持呢? 家里的网络就属于内网IP,之前在家里玩过twonky推送,偶然知晓花生棒.据说花生棒可以穿透内网,搞定内网DDNS动态域名解析,让我得以在远程也能推送.于是,在秒杀活动98元果断下手买了一个.正好手上还有一台QNAP NAS,搭配花生棒使用就能将在旅行时候拍的照片,远程让它出现

使用花生棒穿透内网限制访问黑群辉NAS

 使用花生棒穿透内网限制访问群辉NAS 相信有很多的内网用户,因为种种原因得不到公网IP,无法完成从外网访问内网电脑或个人网络接入服务器(简称NAS).由于白天在公司工作没完成,需要回家继续完成或者工作中需要临时调取家中NAS的数据,这时花生棒就可以派上用场,下面是我用花生棒做的远程穿透局域网限制防问的案例,分享出来与大家一起学习. 首先说明下网络拓扑,我的路由器是二级路由器,(即在一级路由引条网线接入我的路由,然后从我的路由再分别接家里所有电脑,这种情况我的路由就是二级路由器.)如果是三.四…

QQ通信原理及QQ是怎么穿透内网进行通信的?

QQ是一个基于TCP/UDP协议的通讯软件 发送消息的时候是UDP打洞,登陆的时候使用HTTP~因为登陆服务器其实就是一个HTTP服务器,只不过不是常用的那些,那个服务器是腾讯自行开发的!!! 一.登录 QQ客户端在局域网内,当你打开QQ登录到QQ服务器时,通过外网,你的客户端与QQ服务器建立了一个长连接.你可以用netstat -bn  看到此连接的状态是 establish 此时,在QQ服务器那面看到的连接的IP是你们局域网对外的IP.举个例子: QQ服务器      IP:121.115.

使用花生棒穿透内网限制访问群辉NAS

相信有很多的内网用户,因为种种原因得不到公网IP,无法完成从外网访问内网电脑或个人网络接入服务器(简称NAS).由于白天在公司工作没完成,需要回家继续完成或者工作中需要临时调取家中NAS的数据,这时花生棒就可以派上用场,下面是我用花生棒做的远程穿透局域网限制防问的案例,分享出来与大家一起学习. 首先说明下网络拓扑,我的路由器是二级路由器,(即在一级路由引条网线接入我的路由,然后从我的路由再分别接家里所有电脑,这种情况我的路由就是二级路由器.)如果是三.四……级路由应该可以照用,如果是一级路由,也

p2p软件如何穿透内网进行通信

http://blog.chinaunix.net/uid-22326462-id-1775108.html 首先先介绍一些基本概念: NAT(Network Address Translators),网络地址转换:网络地址转换是在IP地址日益缺乏的情况下产生的,它的主要目的就是为了能够地址重用.NAT分为两大类,基本的NAT和NAPT(Network Address/Port Translator). 最开始NAT是运行在路由器上的一个功能模块.最先提出的是基本的NAT,它的产生基于如下事实:

【转】QQ通信原理及QQ是怎么穿透内网进行通信的?

QQ是一个基于TCP/UDP协议的通讯软件 发送消息的时候是UDP打洞,登陆的时候使用HTTP~因为登陆服务器其实就是一个HTTP服务器,只不过不是常用的那些,那个服务器是腾讯自行开发的!!! 一.登录 QQ客户端在局域网内,当你打开QQ登录到QQ服务器时,通过外网,你的客户端与QQ服务器建立了一个长连接.你可以用netstat -bn  看到此连接的状态是 establish 此时,在QQ服务器那面看到的连接的IP是你们局域网对外的IP.举个例子:       QQ服务器      IP:12