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

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using NATUPNPLib;
using System.Threading;
using System.Text.RegularExpressions;
using System.IO;

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");

            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("来自Client的消息:\n{0}", msgRec);
                    }
                }
            });
            serverThread.IsBackground = true;
            serverThread.Start();

            //外网IP变量
            string externalIP;
            //正则
            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("http://checkip.dyndns.org/");
                externalIP = Regex.Match(rawRes, regex).Value;
            }

            Console.WriteLine("获取外网IP成功:" + externalIP);

            Thread clientThread = new Thread(() =>
            {
                ClientConnectToServer(IPAddress.Parse(externalIP), 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);
            }
        }
    }
}

附:源码下载地址: http://download.csdn.net/detail/frombegintoend/5688855

附有Interop.NATUPNPLib.dll

C#用UPnP穿透内网的更多相关文章

  1. n2n网络穿透内网

    目录 前言 配置 网络拓扑: 公网服务器的配置 公司电脑的配置 家里笔记本的配置 注意事项 使用n2n网络 n2n的各edge之间传输数据 补充:NAT类型 后记 前言 在家里的时候比较经常需要对公司 ...

  2. 穿透内网,连接动态ip,内网ip打洞-----p2p实现原理(转)

    源: 穿透内网,连接动态ip,内网ip打洞-----p2p实现原理

  3. 1.使用frp穿透内网

    1.前因后果 1.1弃用ngrok 为节约服务器成本,花了500多块买了一个华为云得1G 1核心 5M得云服务器.然后用ngrok来穿透内网.一直用得还  但是今天在弄nginx得时候发现 ngrok ...

  4. centos7下使用n grok编译服务端和客户端穿透内网

    (发现博客园会屏蔽一些标题中的关键词,比如ngrok.内网穿透,原因不知,所以改了标题才能正常访问,) 有时候想在自己电脑.路由器或者树莓派上搭建一些web.vpn等服务让自己用,但是自己的电脑一般没 ...

  5. frp端口映射穿透内网

    前言 frp 是一个高性能的反向代理应用,可以轻松地进行内网穿透,对外网提供服务,支持 TCP.UDP.HTTP.HTTPS 等协议类型,并且 web 服务支持根据域名进行路由转发. Github: ...

  6. FtpServer穿透内网访问配置踩笔记

    FtpServer穿透内网访问配置踩笔记 引言 FtpServer是服务器文件远程管理常用方式. 以前在局域网配置Ftp服务器以及使用公网上的Ftp服务均未碰到问题,固未对Ftp传输进行深入了解. 然 ...

  7. frp穿透内网使用vsftpd服务

    本篇文章将会介绍如何使用frp穿透内网以及如何在centos8环境下安装和使用vsftpd,最后在公网通过frp穿透内网使用ftp. 一.内网穿透神器frp frp 是一个专注于内网穿透的高性能的反向 ...

  8. QQ通信原理及QQ是怎么穿透内网进行通信的? (转)

    原:http://f543711700.iteye.com/blog/978044#bc2344608 QQ是一个基于TCP/UDP协议的通讯软件 发送消息的时候是UDP打洞,登陆的时候使用HTTP~ ...

  9. [转载]QQ通讯原理及QQ是怎么穿透内网的

    QQ是一个基于TCP/UDP协议的通讯软件 发送消息的时候是UDP打洞,登陆的时候使用HTTP~因为登陆服务器其实就是一个HTTP服务器,只不过不是常用的那些,那个服务器是腾讯自行开发的!!! 一.登 ...

随机推荐

  1. java 12-4 StringBuffer类的替换、反转、截取功能

    1.StringBuffer的替换功能: public StringBuffer replace(int start,int end,String str):从start开始到end用str替换 pu ...

  2. 解说mysql之binlog日志以及利用binlog日志恢复数据

    众所周知,binlog日志对于mysql数据库来说是十分重要的.在数据丢失的紧急情况下,我们往往会想到用binlog日志功能进行数据恢复(定时全备份+binlog日志恢复增量数据部分),化险为夷! 废 ...

  3. POJ 2406 Power Strings

    F - Power Strings Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u S ...

  4. SQL2008安装后激活方式以及提示评估期已过解决方法(转)

    第一步:进入SQL2008配置工具中的安装中心第二步:再进入维护界面,选择版本升级第三步:进入产品密钥,输入密钥第四步:一直点下一步,直到升级完毕.SQL Server 2008 Developer: ...

  5. win安装mysql5.1

    https://dev.mysql.com/downloads/mysql/5.5.html 这里官网下载5.5的安装 我装了几次5.1的,不知道系统有问题还是咋滴,重启mysql服务启动不起来了.擦 ...

  6. Linux 进程通信(共享内存区)

    共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段). 如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映像到自己的私有地址空间中. 如果一个进程更新了段中的数据,其他进程也 ...

  7. OpenGL2.0及以上版本中glm,glut,glew,glfw,mesa等部件的关系

    OpenGL2.0及以上版本中gl,glut,glew,glfw,mesa等部件的关系 一.OpenGL OpenGL函数库相关的API有核心库(gl),实用库(glu),辅助库(aux).实用工具库 ...

  8. 在matlab中进行遥感影像地理坐标的相互转换

    在matlab中进行图像处理,一般使用的都是图像本地坐标,以左上角(1,1)开始.处理完成后,如果要将结果在带地理坐标的遥感影像中显示,或者需要输出成shp文件,就需要涉及到本地坐标和地理坐标的转换, ...

  9. 信息安全系统设计基础第四次实验报告20135324&&20135330

    课程:信息安全系统设计基础 班级:1353 姓名:杨舒雯 张若嘉 学号:20135324,20135330 实验日期:2015.11.17 15:30-17:30 实验名称:外设驱动程序设计 实验目的 ...

  10. Java实验四 TCP客户端和服务器的应用

    实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全 4.对通信内容进行摘要计算并验证 实验步骤 1.信息安全传送: 发送方A——————>接收方B A加密时,用B ...