万金流
以码会友。 吾Q:578751655。 水平有限,轻喷,谢!
随笔 - 189,  文章 - 0,  评论 - 7,  阅读 - 14万

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中显示目标计算机积极拒绝。

posted on   万金流  阅读(502)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现

点击右上角即可分享
微信分享提示