文档章节

Kestrel的ListenAnyIP和ListenLocalhost的区别

李明成
 李明成
发布于 07/29 07:30
字数 1148
阅读 1K
收藏 0

行业解决方案、产品招募中!想赚钱就来传!>>>

问题

在上篇文章,把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等同于ListenIPAddress.IPv6LoopbackIPAddress.LoopbackListenAnyIP等同于Listen的IPAddress.IPv6AnyIPAddress.Any。下面我看看可以查看他们的源代码。

ListenLocalhost、ListenAnyIP 两个方法的源码


/// <summary>
/// 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.
/// </summary>
public void ListenLocalhost(int port, Action<ListenOptions> configure)
{
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}

var listenOptions = new LocalhostListenOptions(port);
ApplyEndpointDefaults(listenOptions);
configure(listenOptions);
ListenOptions.Add(listenOptions);
}
    /// <summary>
/// Listens on all IPs using IPv6 [::], or IPv4 0.0.0.0 if IPv6 is not supported.
/// </summary>
public void ListenAnyIP(int port, Action<ListenOptions> 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);
}
}

//绑定回环地址ipv4127.0.0.1 iPV6::1
internal override async Task BindAsync(AddressBindContext context)
{
var exceptions = new List<Exception>();

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

小结:通过以上分析,端口绑定时,建议使用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);
});

参考:https://juejin.im/post/5d258b6ae51d454f73356dcf


本文分享自微信公众号 - dotNET知音(AAshiyou)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

李明成
粉丝 1
博文 204
码字总数 40555
作品 0
私信 提问
加载中
请先登录后再评论。
JPA 各种实体锁模式的区别

为了能够同步访问实体,JPA提供了2种锁机制。这两种机制都可以避免两个事务中的其中一个,在不知情的情况下覆盖另一个事务的数据。 通过实体锁,我们通常希望避免在两个并行事务中产生如下情...

重度恐高症
2016/02/18
36
0
谈谈链接属性的defer async 区别

有时候我们加载JS文件, 尤其是外链JS文件的时候,当文件加载过慢,或者文件加载出错的时候,有可能会阻塞整个页面的加载, 这时我们需要JS的异步加载, 有两个属性可支持异步加载 defer as...

r00txx
2016/06/22
374
3
JDK与JRE的区别,还有JVM

  JDK就是Java Development Kit.简单的说JDK是面向开发人员使用的SDK,它提供了Java的开发环境和运行环境。SDK是Software Development Kit 一般指软件开发包,可以包括函数库、编译程序等。...

aineice
2015/08/25
116
0
PHP echo,print,printf,sprintf函数之间的区别与用法详解

echo函数: 输出函数,是命令,不能返回值。echo后面可以跟很多个参数,之间用分号隔开,如: echo $myvar1; echo 1,2,$myvar,"bold"; 2. print函数: 是函数,可以返回一个值,只能有一个参...

linghangp
2013/11/27
256
0
apache里面的FTPClient中方法logout与disconnect区别

请教下高手,apache里面的FTPClient中,方法logout与disconnect的区别,我刚学JAVA不久...

秋雨
2011/04/21
9.6K
1

没有更多内容

加载失败,请刷新页面

加载更多

鼠年吉祥,新年快乐

今天是大年初一,很高兴在过去一年中有您的陪伴,希望大家在新的一年中平安健康,一切顺利,加油。 邓飞 202001250539 于后园爷爷家 本文分享自微信公众号 - 育种数据分析之放飞自我(R-bre...

育种数据分析之放飞自
01/25
0
0
不烧脑、不耗时、全免费,带你0基础学Python

文末有福利 Python是人工智能的未来。 最近,电气和电子工程师协会( IEEE)发布了顶级编程语言交互排行榜:Python高居首位。 而且随着大数据和人工智能的发展,Python受到了越来越多程序员的...

kunjian
今天
0
0
R语言入门系列之一

写在前面 计算机语言的学习并不困难,关键是一定要由浅入深的实际操作练习。也许最开始的比较简单,学习者一带而过没有实际操作,之后的进一步学习很可能会陷入不知所云的困境,实际操作所带...

SYSU星空
2019/02/17
0
0
Istio-本地运行

概述 基于上一篇 Istio1.6-二进制编译和本地运行 但集中在 pilot-discovery 和 envoy(pilot-agent 大部分功能仅作为 envoy 的 watchdog,略过) NOTE: 以下的描述,相对路径都基于目录 /g...

深蓝苹果
26分钟前
9
0
基于Linux、C、JSON、Socket的编程实例(附代码)

点击上方「嵌入式大杂烩」,选择「置顶公众号」第一时间阅读编程笔记! 一、前言 之前在学习socket编程的时候有分享一个基于控制台的简易天气客户端的实现,当时提供的是window下的代码,最近...

学以解忧
2019/10/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部