zoukankan      html  css  js  c++  java
  • 关于地址映射穿透和套接字复用的说明

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

  • 相关阅读:
    复杂声明的正确解读(*、()、[])
    (多张图片打包为Zip返回前端下载) 记NetCore HttpClient.GetStreamAsync()返回只读流,Stream的Length属性不可用,报错的问题。
    ### Vue开发环境搭建
    计算机网络原理----CRC编码相关问题及解题思路
    CentOS7安装MongoDB4.4.4
    树莓派4B安装.NET Core 3.1 SDK
    基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(TableGo v7.0.0版)
    解决Unity启动报错 Assertion failed on expression: 'SUCCEEDED(hr)'
    @RabbitListener注解导致spring bean注入属性为空 解决方案
    一文彻底讲透@Async注解的原理和使用方法
  • 原文地址:https://www.cnblogs.com/wanjinliu/p/12789217.html
Copyright © 2011-2022 走看看