zoukankan      html  css  js  c++  java
  • Kestrel的ListenAnyIP和ListenLocalhost的区别

      把AAStore.ProductCatalog.Api部署到docker中运行,输入地址访问报错如下图,说明外部无法访问这个url。(当然本地开发环境测试是可以访问的)。后来修改此处options.ListenLocalhost(8081)的代码改成options.ListenAnyIP(8081),可以访问了。那这两种写法有什么区别呢?

      

      在区别之前,我们先熟悉几个概念(如果网络知识比较好的,可以跳过):

      本地回环地址(Loopback Address):

      百度定义的定义,127.0.0.1,通常被称为本地回环地址(Loopback Address),不属于任何一个有类别地址类。它代表设备的本地虚拟接口,所以默认被看作是永远不会宕掉的接口。在Windows操作系统中也有相似的定义,所以通常在安装网卡前就可以ping通这个本地回环地址。一般都会用来检查本地网络协议、基本数据接口等是否正常的。

      IPv6的本地回环地址形式:0:0:0:0:0:0:0:1,同IPV4中127.0.0.1地址的含义一样,表示节点自已,也可以是::1,大多数windows和linux电脑上都将localhost指向了127.0.0.1这个地址,相当于是本机地址。

      ip地址类型

      公有地址

      公有地址(Public address)由Inter NIC(Internet Network Information Center因特网信息中心)负责。这些IP地址分配给注册并向Inter NIC提出申请的组织机构。通过它直接访问因特网。

      私有地址

      私有地址(Private address)属于非注册地址,专门为组织机构内部使用。以下列出留用的内部私有地址

      A类 10.0.0.0--10.255.255.255

      B类 172.16.0.0--172.31.255.255

      C类 192.168.0.0--192.168.255.255

      IPv6 [::] ( 0000:0000:0000:0000:0000:0000:0000:0000的简写), IPv4 0.0.0.0 含义:

      维基百科解释,表示无效的,未知,不可用的目标

      在服务器中,常常表示监听本机所有的ip地址。一般我们在服务端绑定端口的时候可以选择绑定到0.0.0.0,这样就可以通过多个ip地址访问我的服务。

      ListenLocalhost 和ListenAnyIP 区别

      通过编码配置Kestrel监听端口有三个方法可以实现ListenLocalhost、ListenAnyIP、Listen,其中ListenLocalhost等同于Listen的IPAddress.IPv6Loopback 和IPAddress.Loopback,ListenAnyIP等同于Listen的IPAddress.IPv6Any和IPAddress.Any。下面我看看可以查看他们的源代码。

      ListenLocalhost、ListenAnyIP 两个方法的源码

      /// /// Listens on ::1 and 127.0.0.1 with the given port. Requesting a dynamic port by specifying 0 is not supported /// for this type of endpoint. /// public void ListenLocalhost(int port, Action configure) { if (configure == null) { throw new ArgumentNullException(nameof(configure)); } var listenOptions = new LocalhostListenOptions(port); ApplyEndpointDefaults(listenOptions); configure(listenOptions); ListenOptions.Add(listenOptions); }

      /// /// Listens on all IPs using IPv6 [::], or IPv4 0.0.0.0 if IPv6 is not supported. /// public void ListenAnyIP(int port, Action configure) { if (configure == null) { throw new ArgumentNullException(nameof(configure)); } var listenOptions = new AnyIPListenOptions(port); ApplyEndpointDefaults(listenOptions); configure(listenOptions); ListenOptions.Add(listenOptions); }

      通过源码我们可以发现,他们之间的区别是在构造listenopthons对象不同,分别使用LocalhostListenOptions和AnyIPListenOptions进行new创建实例,而AnyIPListenOptions和LocalhostListenOptions都继承类ListenOptions,并且重写BindAsync方法。源码如下:

      internal sealed class LocalhostListenOptions : ListenOptions { internal LocalhostListenOptions(int port) : base(new IPEndPoint(IPAddress.Loopback, port)) { if (port == 0) { throw new InvalidOperationException(CoreStrings.DynamicPortOnLocalhostNotSupported); } } //绑定回环地址ipv4是127.0.0.1 ,iPV6是::1 internal override async Task BindAsync(AddressBindContext context) { var exceptions = new List(); try { var v4Options = Clone(IPAddress.Loopback); await AddressBinder.BindEndpointAsync(v4Options, context).ConfigureAwait(false); } catch (Exception ex) when (!(ex is IOException)) { context.Logger.LogWarning(0, CoreStrings.NetworkInterfaceBindingFailed, GetDisplayName(), "IPv4 loopback", ex.Message); exceptions.Add(ex); } try { var v6Options = Clone(IPAddress.IPv6Loopback); await AddressBinder.BindEndpointAsync(v6Options, context).ConfigureAwait(false); } catch (Exception ex) when (!(ex is IOException)) { context.Logger.LogWarning(0, CoreStrings.NetworkInterfaceBindingFailed, GetDisplayName(), "IPv6 loopback", ex.Message); exceptions.Add(ex); } if (exceptions.Count == 2) { throw new IOException(CoreStrings.FormatAddressBindingFailed(GetDisplayName()), new AggregateException(exceptions)); } // If StartLocalhost doesn't throw, there is at least one listener. // The port cannot change for "localhost". context.Addresses.Add(GetDisplayName()); } }

      internal sealed class AnyIPListenOptions : ListenOptions { internal AnyIPListenOptions(int port) : base(new IPEndPoint(IPAddress.IPv6Any, port)) { } //如果本机不支持 IPv6就绑定ipv4 internal override async Task BindAsync(AddressBindContext context) { // when address is 'http://hostname:port', 'http://*:port', or 'http://+:port' try { await base.BindAsync(context).ConfigureAwait(false); } catch (Exception ex) when (!(ex is IOException)) { context.Logger.LogDebug(CoreStrings.FormatFallbackToIPv4Any(IPEndPoint.Port)); // for machines that do not support IPv6 EndPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.Port); await base.BindAsync(context).ConfigureAwait(false); } } }

    参考:

      郑州同济医院:http://jbk.39.net/yiyuanzaixian/zztjyy/

      郑州做人工授精多少钱:http://yyk.39.net/hospital/fc964_detail.html

      小结:通过以上分析,端口绑定时,建议使用IPAddress.Any,可以支持ipv6和ipv4地址。

      webBuilder.ConfigureKestrel(options => { //1.ListenLocalhost方法 //options.ListenLocalhost(8081); //2.ListenAnyIP方法 options.ListenAnyIP(8081); //3.Listen方法 // options.Listen(IPAddress.Loopback, 8081); // Setup a HTTP/2 endpoint without TLS. options.ListenAnyIP(18081, o => o.Protocols = HttpProtocols.Http1AndHttp2); });

  • 相关阅读:
    浅谈JavaScript中this指向的⼏种情况
    JavaScript、html简单的级联操作。
    异常处理中throws和throw的区别?
    java异常处理try-catch-finally的执行过程?
    什么是内连接、外连接、交叉连接(笛卡尔积)?
    主键和外键的区别
    集合和数组的比较(为什么要引入集合)?
    Java中对比单继承与多继承的优劣,以及java的解决方案
    数据库
    数据库集中控制的优势
  • 原文地址:https://www.cnblogs.com/sushine1/p/13403999.html
Copyright © 2011-2022 走看看