关于地址映射穿透和套接字复用的说明

1、关于地址映射的穿透,实测UDP可以,TCP不可以。

  从道理上来说,TCP作为有连接传输,在nat设备上应该是匹配了对端ip地址的;但更有可能,出口设备做了阻止外到内tcp连接的acl。UDP应该没有,所以任意ip可以向nat设备的对应端口发包,内网机器都能收到。

2、关于套接字复用

s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

之后,确实可以对套接字s0使用正在使用的节点。但最好对重复使用的两个套接字都指定复用,否则还是会报错。(实作指定后一个可以,后来必须两个都指定。懒得找原因了)

附:本次TCP测试的三个程序代码:

  a、服务端程序(.net core)

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpListener listener = new TcpListener(IPAddress.Any, 9000);
            listener.Start();
            var tcp = listener.AcceptTcpClient();
            var sr = new StreamReader(tcp.GetStream());
            string msg = "";
            do
            {
                msg = sr.ReadLine();
                Console.WriteLine($"{tcp.Client.RemoteEndPoint.ToString()}:{msg}");
            } while (msg.ToLower()!="exit");
        }
    }
}

  b、客户端程序,模拟内网用户,希望能穿透nat(.net core)

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace App2
{
    class Program
    {
        static void Main(string[] args)
        {
            IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("自己的ip"), 9100);
            
            string msg="";
            
            Socket s0 = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
            s0.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            s0.Bind(ipe);
            s0.Connect(IPAddress.Parse("服务器ip"), 9000);
            var sw = new StreamWriter(new NetworkStream(s0));
            //

            try
            {
                do
                {
                    msg = Console.ReadLine();
                    sw.WriteLine(msg);
                    sw.Flush();
                } while (msg.ToLower()!="next");
            }
            catch (Exception e)
            {
                Console.WriteLine($"写入失败:{e.Message}");
            }

            Console.WriteLine("开始进入监听状态:");
            Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp),s1;
            s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            s.Bind(ipe);
            s.Listen(20);
            s1 = s.Accept();
            Console.WriteLine($"{s1.RemoteEndPoint.ToString()}已连接...");
            var sr = new StreamReader(new NetworkStream(s1));
            do
            {
                msg = sr.ReadLine();
                Console.WriteLine($"{s1.RemoteEndPoint.ToString()}:{msg}");
                msg = Console.ReadLine();
                sw.WriteLine(msg);
                sw.Flush();
            } while (msg.ToLower() != "exit");
        }
    }
}

  c、另一个用户(.net framework)

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

namespace App4
{
    class Program
    {
        static void Main(string[] args)
        {
            IPEndPoint ipe = new IPEndPoint(IPAddress.Any, 9200);
            string ip;
            int port;
            Console.WriteLine("请输入ip:");
            ip = Console.ReadLine();
            Console.WriteLine("请输入port:");
            port = int.Parse(Console.ReadLine());

            TcpClient tcp = new TcpClient(ipe);
            Console.WriteLine("输入任意键开始连接");
            Console.ReadKey();
            tcp.Connect(IPAddress.Parse(ip), port);

            var sw = new StreamWriter(tcp.GetStream());
            string msg = "";

            try
            {
                do
                {
                    sw.WriteLine(Console.ReadLine());
                    sw.Flush();
                } while (msg.ToLower() != "next");
            }
            catch (Exception e)
            {
                Console.WriteLine($"写入失败:{e.Message}");
            }
        }
    }
}

实验过程:1启动,2启动,任意输入验证,输入next进入监听模式,3启动,输入1读出的ip和port

实验结果:2、3程序在本机:通过;2、3程序分别部署:3中显示目标计算机积极拒绝。

原文地址:https://www.cnblogs.com/wanjinliu/p/12789217.html