Apple - DNS Service Discovery Programming Guide
本文翻译整理自:DNS Service Discovery Programming Guide(更新日期:2013-08-08
https://developer.apple.com/library/archive/documentation/Networking/Conceptual/dns_discovery_api/Introduction.html#//apple_ref/doc/uid/TP30000964
文章目录
- 一、DNS服务发现简介
- 1、谁应该阅读此文档?
- 2、文档组织
- 3、在你开始之前
- 4、要求
- 5、限制
- 6、更多信息
- 二、注册和终止服务
- 1、注册服务
- 2、终止服务注册
- 三、浏览网络服务
- 1、使用DNSServiceBrowse
- 2、浏览多个域
- 3、终止浏览
- 四、解析服务的当前地址
- 1、使用DNSServiceResolve
- 2、设置回调函数
- 五、枚举域
- 六、在Windows中使用DNS服务发现
- 1、Windows图形用户界面
- 2、Windows命令行界面
一、DNS服务发现简介
本文档介绍如何在您的程序中使用DNS服务发现API。
重要提示: iOS和OS X中的大多数应用程序不应该使用此API,而是应该使用更高级别的API,例如NSNetService
类。
有关详细信息,请参阅 NSNetServices和CFNetServices编程指南 。
DNS服务发现API可帮助您执行三项主要任务:
- 注册服务
- 浏览服务
- 将服务名称解析为主机名
为了支持这些主要任务,此API可以直接帮助您执行两个辅助任务:
- 枚举域(查找推荐的服务域)
- 更新注册(动态更改您的DNS注册数据)
DNS服务发现API是Bonjour的一部分,Bonjour是Apple的零配置网络(ZEROCONF)实现。
有关Bonjour工作原理的概述,请在使用DNS服务发现之前阅读 Bonjour概述 。
注意:本文档描述了基于套接字的DNS服务发现API,这是OS X v10.3及更高版本以及所有iOS版本中可用的推荐API。
不推荐使用基于马赫的替代API(并且在iOS中不受支持)。
1、谁应该阅读此文档?
本文档适用于希望在其应用程序中使用Bonjour的开发人员。
在网络服务API(NSNetServices和CFNetServices)上使用DNS服务发现API的原因有很多:
- 您正在编写不需要链接到更高级别框架的BSD风格的应用程序。
- 您正在编写跨平台程序(DNS Service Discovery API可在iOS、OS X、Windows和其他POSIX兼容操作系统上使用)。
- 您正在编写一个需要特殊用途的低级例程的应用程序,例如注册单个记录或只能使用特定的网络接口。
如果您的程序不需要这些功能,强烈建议您先查看NSNetService和CFNetService。
2、文档组织
本文档包含以下内容:
- 注册和终止服务说明了如何使用
mDNSResponder
守护程序注册和终止服务。 - 浏览网络服务描述了如何浏览服务。
- 解析服务的当前地址说明如何根据服务名称、注册类型和域获取服务信息。
- 枚举域有助于您了解如何查找推荐注册和浏览的域。
- 在Windows中使用DNS服务发现概述了如何在基于Windows的应用程序中实现DNS服务发现。
3、在你开始之前
接下来的几段描述了在尝试任何任务之前您应该了解的有关此API的一些信息。
此API中的大多数函数不会使用其函数返回或参数块返回所有数据。
相反,它们要求您提供一个可以处理异步发送的数据的回调函数。
您的回调函数可能会被多次调用,以响应您的单个函数调用。
例如,您可能会请求可用服务列表。
对于与您的请求匹配的每个可用服务,您的回调将被调用一次,然后在添加或删除匹配服务时再次调用。
一些函数以通常的方式返回错误代码,但许多函数没有。
在这些情况下,任何错误代码和状态标志都作为异步回复的一部分发送到您的回调函数,连同或代替任何返回的数据。
此API中的大多数函数使用一组通用参数来描述服务。
您将需要提供部分或全部这些参数,具体取决于您调用的目的。
在许多情况下,您将提供一些参数,例如服务的域和类型,并且您的回调函数将接收与其他参数对应的数据,例如匹配服务的服务名称。
以下是DNS Service Discovery API所需的常用参数列表:
-
名称-服务的人类可读名称,例如
Sales Laser Printer
。 -
注册类型-服务类型后跟协议名称并用点(
.
)分隔;_printer._tcp
就是一个例子。 -
域-服务的域,通常为
NULL
。 -
完整域名-唯一标识服务的名称。
完整域名是名称、注册类型和域的串联。
因为点(.
)字符用作分隔符,所以完整域名名称部分中的任何点字符都必须用反斜杠字符(\
)转义。
如果名称包含文字反斜杠,反斜杠也必须用反斜杠字符转义。
以下是完整域名的示例:Dr\.Smith’s Home\\Office Server._http._tcp.local
. -
端口-按网络字节顺序排列的服务端口号。
-
文本记录-包含使用服务可能需要的任何附加信息的可选记录,例如打印队列名称。
4、要求
DNS Service Discovery API需要mDNSResponder
守护程序的服务。
OS X(版本10.2及更高版本)和iOS包含一个mDNSResponder
守护程序作为操作系统的一部分。
Apple还在Apple的开源站点上提供了其mDNSResponder
守护程序的源代码。
此API也可在Bonjour for Windows和(如果安装了mDNSResponder
)Linux、Solaris和FreeBSD操作系统中使用。
**注意:**Apple鼓励硬件开发人员在其硬件中嵌入DarwinmDNSResponder
守护程序代码。
5、限制
DNS Service Discovery API不对服务执行网络访问设置。
同样,DNS Service Discovery API不提供从应用程序到服务的网络连接。
它允许应用程序浏览服务,或按名称请求服务,并提供IP地址、端口等。
您可以使用BSD套接字通过网络连接到服务。
6、更多信息
有关Bonjour的其他信息,包括标准、规范和资源的链接,请参阅http://developer.apple.com/networking/bonjour并阅读 Bonjour概述 。
有关基于Java的DNS服务发现API的文档,请参阅DNS服务发现Java参考。
有关动态更新和共享机密的信息,请分别参阅http://www.ietf.org/rfc/rfc2136.txt和http://www.ietf.org/rfc/rfc2845.txt。
有关网络地址转换(NAT)的信息,请参见http://www.ietf.org/rfc/rfc3022.txt,有关自动NAT端口映射的信息,请参见http://files.dns-sd.org/draft-nat-port-mapping.txt。
有关示例代码,请在Apple的开源站点下载mDNSResponder
源代码。
二、注册和终止服务
当您的服务启动时,您需要向mDNSResponder
守护程序注册,以便应用程序可以发现您的服务。
本节提供该过程的一般概述,然后是一组分步说明。
1、注册服务
要注册您的服务,请调用DNSServiceRegister
。
进行此调用的参数包括以下内容:
- 未初始化的服务发现引用。
- 要在其上注册服务的接口的索引;传递
0
以在所有可用接口上注册,传递–1
以仅在本地计算机上注册(远程主机无法使用您的服务),或传递表示要在其上注册的接口的编号(使用if_nametoindex
系列调用获取编号)。 - 指示您希望如何处理名称冲突的标志。
默认情况下,如果发生名称冲突,(
n)
会自动附加到您的服务名称,其中n是一个数字。
要覆盖此行为,请设置kDNSServiceFlagsNoAutoRename
标志,这将导致调用您的注册回调函数,以便您可以处理名称冲突。
kDNSServiceFlagsNoAutoRename
标志仅在您还显式指定服务名称时有效。 - 服务的名称;您可以指定
NULL
以使用计算机的名称作为服务的名称。 - 服务的注册类型。
- SRV目标主机名;通常,您将传递
NULL
以使用计算机的默认主机名。
几乎在所有情况下,传递NULL
都是所需的行为。
但是,代理应用程序可能会传递计算机主机名以外的显式SRV目标。 - 服务接受连接的网络字节顺序的端口号。
端口传递0
将注册占位符服务。
使用占位符服务,浏览不会发现该服务,但如果另一个客户端尝试注册相同的名称,则会发生名称冲突。
大多数应用程序不需要使用占位符服务。 - 要调用的回调函数,用于提供有关注册成功或失败的信息,或
NULL
。 - 调用回调函数时将传递给回调函数的用户定义上下文值,
NULL
。
需要TXT记录的服务也传递TXT记录的原始数据和原始数据的长度作为参数。
大多数服务不需要TXT记录,因此这些参数分别传递NULL
和0
。
您可以传递NULL
,而不是提供回调函数,在这种情况下,您将不会收到代表您选择的默认值的通知,也不会收到任何可能阻止您的服务注册的异步错误的通知。
如果您为此参数传递NULL
,则不能传递kDNSServiceFlagsNoAutoRename
作为标志参数。
您可以通过调用DNSServiceRefDeallocate
.
如果注册可以启动,DNSServiceRegister
初始化服务发现引用并创建一个套接字,用于与mDNSResponder
守护进程通信。
使用服务发现引用调用DNSServiceRefSockFD
并获取服务引用的套接字描述符。
使用套接字描述符设置运行或select
循环。
当循环指示mDNSResponder
守护进程的回复可用时,调用DNSServiceProcessResult
并向其传递由DNSServiceRegister
初始化的服务发现引用。
DNSServiceProcessResult
将调用与服务发现引用关联的回调函数。
您可以调用DNSServiceRegister
并立即调用DNSServiceProcessResult
,而不是设置运行循环或select
循环。
DNSServiceProcessResult
函数将阻塞,直到mDNSResponder
守护进程有响应,此时将调用调用DNSServiceRegister
时指定的回调(如果有)。
除了当前未使用的服务发现引用和标志之外,您的回调将使用以下参数调用:
- 指示注册是否成功的错误代码;如果注册成功,则其余参数包含有效数据
- 传递给
DNSServiceRegister
的服务名称,或者在传递给DNSServiceRegister
作为服务名称时选择NULL
的名称 - 传递给
DNSServiceRegister
- 注册服务的域
- 传递给DNSServiceRegister的用户定义
DNSServiceRegister
如果服务名称、注册类型和域名的组合导致完整域名已在本地使用并且您指定了kDNSServiceFlagsNoAutoRename
,则需要解除分配服务发现引用,选择另一个服务名称并重试,直到可以注册本地唯一名称。
成功注册后,您的服务将被通知到本地网络,并且可以使用多播DNS(按名称或浏览服务)找到其访问信息(IP地址、端口等)。
使用初始化的服务发现引用,您可以与mDNSResponder
守护程序通信,以便在服务运行时向服务的注册信息添加记录、更新添加的记录或删除添加的记录。
但是,您可能永远不需要更改注册信息,因为Bonjour处理常见情况,例如唤醒、睡眠、关闭和更改IP地址。
一个罕见的例外是需要更新与服务关联的文本记录。
例如,如果文本字段包含队列名称,并且队列名称发生更改,则需要更新服务的文本记录。
只要期望调用回调函数,就必须将套接字描述符保留在运行循环或select
循环中。
2、终止服务注册
要终止服务的注册,请从运行循环或select
循环中删除套接字描述符并调用DNSServiceRefDeallocate
,将注册服务时初始化的服务发现引用传递给它。
除了使服务发现引用无效并释放与之关联的内存之外,任何已添加的资源记录都将取消注册并且它们的引用将无效。
与mDNSResponder
守护程序连接的基础套接字将关闭,从而终止应用程序与守护程序的连接。
三、浏览网络服务
使用此API浏览服务相当简单。
您可以通过单个函数调用找出给定域中可用的给定类型的服务。
1、使用DNSServiceBrowse
要浏览可用服务,请调用DNSServiceBrowse
。
进行此调用的参数包括以下内容:
- 未初始化的服务发现引用。
- 要浏览的接口的索引;传递
0
以浏览所有可用接口,传递–1
以仅浏览本地主机上的服务,或传递表示要浏览的接口的编号(使用if_nametoindex
系列调用获取编号)。 - 要浏览的服务的注册类型;注册类型是服务类型,后跟一个点,后跟协议(例如,
_printer._tcp
)。 - 要浏览的域;传递
NULL
以浏览用户指定为可浏览的域,或传递域名以仅浏览该域。 - 要调用的回调函数,以提供有关浏览成功或失败的信息并提供搜索结果,例如已找到的服务或不再可用的服务。
- 调用回调函数时将传递给回调函数的用户定义上下文值,
NULL
。
如果可以启动浏览,DNSServiceBrowse
会初始化服务发现引用并创建一个套接字,用于与mDNSResponder
守护程序通信。
使用服务发现引用调用DNSServiceRefSockFD
并获取套接字的套接字描述符。
使用套接字描述符设置一个运行循环或select
循环,该循环将指示何时来自mDNSResponder
守护进程的响应变得可用。
该响应可能指示已找到与指定类型、域和接口匹配的服务实例,或者先前找到的服务实例不再可用。
当循环指示mDNSResponder
守护进程已响应时,调用DNSServiceProcessResult
并向其传递由DNSServiceBrowse
初始化的服务发现引用。
DNSServiceProcessResult
将调用与服务发现引用关联的回调函数。
您的回调将使用以下参数调用:
- 由
DNSServiceBrowse
初始化的服务发现引用。 - 提供已找到或不再可用的服务和浏览状态信息的标志。
例如,kDNSServiceFlagsAdd
表示服务参数包含已找到的服务的名称;您应该将其添加到您的可用服务列表中。
如果kDNSServiceFlagsAdd
未设置,则服务参数指定的服务不再可用,应从您的可用服务列表中删除。
浏览状态由kDNSServiceFlagsMoreComing
标志指示。
设置时,您的回调函数将立即再次调用,因此您不应该更新您的用户交互界面。
当kDNSServiceFlagsMoreComing
未设置时,您的回调函数将不会立即再次调用,因此您有时间更新您的用户交互界面。 - 发现服务的接口的索引。
- 指示浏览是否成功的错误代码;如果浏览成功,其余参数包含有效数据。
- 如果浏览成功,则找到的服务的名称。
- 注册类型,如果浏览成功。
- 如果浏览成功,则发现服务的域。
- 传递给
DNSServiceBrowse
的用户定义上下文信息。
2、浏览多个域
要浏览多个域或多个服务类型,请为感兴趣的每个域和服务类型调用DNSServiceBrowse
。
您的应用程序负责跟踪响应。
**注意:**您可以通过调用DNSServiceEnumerateDomains
获取要搜索的推荐域列表。
有关详细信息,请参阅枚举域。
如果您的应用程序需要在应用程序运行的整个过程中保持浏览器界面可见,就像iTunes和iChat所做的那样,那么您通常会在每个会话中调用一次DNSServiceBrowse
。
每当有新服务可用或现有服务不可用时,数据都会发送到您的回调函数,因此您只需保持回调处于活动状态,您的服务列表将始终是最新的。
此信息通常不经常更改,因此回调通常不会使用太多CPU时间。
但是,如果您的应用程序不需要在打印机对话框等情况下不断显示可用服务列表,那么您应该调用DNSServiceBrowse
并在完成后终止浏览。
当您调用DNSServiceBrowse
时,它会初始化一个服务发现引用,并打开一个基于套接字的连接与mDNSResponder
守护程序。
因此,如果您选择停用回调并根据需要重复搜索,请务必在再次调用DNSServiceBrowse
之前调用DNSServiceRefDeallocate
以释放引用。
否则,每次搜索都会泄漏内存和套接字。
给定服务实例的实际IP地址和端口将比服务名称更频繁地更改。
每次使用服务时,您都应该在使用服务之前解析服务实例的当前地址。
请参阅下一节,解析服务的当前地址。
3、终止浏览
要终止浏览,请从运行循环或select
循环中删除套接字描述符并调用DNSServiceRefDeallocate
,将调用DNSServiceBrowse
时初始化的服务发现引用传递给它。
浏览停止,服务发现引用无效,与引用关联的内存被释放。
与mDNSResponder
守护程序连接的基础套接字关闭,从而终止应用程序与守护程序的连接。
四、解析服务的当前地址
本文介绍如何使用DNSServiceResolve
根据名称、类型和域获取有关服务的信息。
1、使用DNSServiceResolve
一旦获得了服务的名称、注册类型和域,您就可以通过调用DNSServiceResolve
来获取有关服务的信息,例如注册服务的接口、服务的完整域名、提供服务的主机的名称以及服务的主TXT记录的内容。
警告: DNSServiceResolve
适用于获取有关具有单个SRV记录和单个TXT记录(可能为空)的服务的信息。
要解析具有多个SRV或TXT记录的服务,您应该使用DNSServiceQueryRecord
您还应该使用DNSServiceQueryRecord
来监视TXT记录内容,而不是DNSServiceResolve
。
要将服务名称解析为其主机名和端口,请调用DNSServiceResolve
。
进行此调用的参数包括以下内容:
- 未初始化的服务发现引用
- 要解析服务的接口的索引;传递传递给
DNSServiceBrowse
回调函数的值,或0
以在所有可用接口上解析 - 要解析的服务名称;传递传递给DNSServiceBrowse回调函数的
DNSServiceBrowse
- 要解析的服务的注册类型;将传递给DNSServiceBrowse回调函数的值
DNSServiceBrowse
- 注册服务的域;传递传递给DNSServiceBrowse回调函数的
DNSServiceBrowse
- 要调用的回调函数,以提供有关解析成功或失败的信息
- 调用时将传递给回调函数的用户定义上下文值,或
NULL
如果解析可以启动,DNSServiceResolve
会初始化服务发现引用并创建一个套接字,用于与mDNSResponder
守护进程通信。
使用服务发现引用调用DNSServiceRefSockFD
并获取套接字的套接字描述符。
2、设置回调函数
如果DNSServiceResolve
返回无错误,您需要让mDNSResponder
解析服务发现引用,并在收到响应时运行回调函数。
设置回调函数有两种技术:异步和同步。
若要从mDNSResponder
异步获取响应,请使用套接字描述符设置运行或select
循环。
每当来自mDNSResponder
守护进程的响应可用时,将通知该循环。
当循环指示响应可用时,调用DNSServiceProcessResult
并将由DNSServiceResolve
初始化的服务发现引用传递给它。
DNSServiceProcessResult
将调用与服务发现引用关联的回调函数。
mDNSResponder
守护进程将为它基于每个接口解析的每个服务提供响应。
如果您想同步运行回调函数,而不是设置运行循环或select
循环,您可以调用DNSServiceResolve
并立即调用DNSServiceProcessResult
。
DNSServiceProcessResult
函数将阻塞,直到mDNSResponder
守护进程有响应,此时将调用调用DNSServiceResolve
时指定的回调。
对于您希望解析的每个服务,整个过程可能应该在其自己的循环中运行。
除了当前未使用的服务发现引用和标志之外,您的回调将使用以下参数调用:
- 解析服务的接口索引;使用
if_nametoindex
系列调用将索引与接口名称相关联 - 指示解析是否成功的错误代码;如果解析成功,则其余参数包含有效数据
- 服务的完整域名,适合传递给以完整域名为参数的特殊用途函数
- 提供服务的机器的主机名,适合传递给
gethostbyname
或DNSServiceQueryRecord
获取主机的IP地址 - 服务接受连接的网络字节顺序的端口号
- 服务的TXT记录长度
- 标准TXT记录格式的服务的主TXT记录(即一个长度字节后跟数据,后跟一个长度字节,后跟数据,依此类推)
- 传递给DNSServiceResolve的用户定义
DNSServiceResolve
重要提示:服务的IP地址和端口号可以动态更改,因此您应该在每次使用服务时获取当前地址,就在使用之前。
将为解析服务的每个接口以及与服务关联的每个TXT记录通知您的运行循环或select
循环。
获得所需结果后,您必须终止解析。
从运行循环或select
循环中删除套接字描述符并调用DNSServiceRefDeallocate
,将调用DNSServiceResolve
时初始化的服务发现引用传递给它。
服务发现引用无效,与该引用关联的内存被释放。
与mDNSResponder
守护程序连接的基础套接字关闭,从而终止应用程序与守护程序的连接。
五、枚举域
该DNSServiceEnumerateDomains
函数查找建议注册和浏览的域。
每次调用回调时,都会提供有关一个域的信息,以及指示是否从域列表中添加或删除该域或指示该域是默认域或不再是默认域的标志。
用于调用DNSServiceEnumerateDomains
的参数包括:
- 未初始化的服务发现引用
- 一个标志,指示是否要枚举推荐的浏览或注册域
- 指定要枚举的接口的接口索引;传递
0
来枚举所有接口上的域,或者传递正整数来指定要枚举域的接口(使用if_nametoindex
系列调用来获取要枚举的接口的索引) - 要调用的回调函数以提供有关枚举成功或失败的信息
- 调用时将传递给回调函数的用户定义上下文值,或
NULL
如果可以启动枚举,DNSServiceEnumerateDomains
初始化服务发现引用并创建用于与mDNSResponder
守护程序通信的套接字。
使用服务发现引用调用DNSServiceRefSockFD
并获取套接字描述符。
使用套接字描述符设置运行循环或select
循环。
当循环指示来自mDNSResponder
守护进程的响应可用时,调用DNSServiceProcessResult
并将由DNSServiceEnumerateDomains
初始化的服务发现引用传递给它。
DNSServiceProcessResult
将调用与服务发现引用关联的回调函数。
无需设置运行或select
循环,您可以调用DNSServiceEnumerate
并立即调用DNSServiceProcessResult
。
DNSServiceProcessResult
函数将阻塞,直到mDNSResponder
守护进程有响应,此时将调用调用DNSServiceEnumerate
时指定的回调。
您的回调将使用以下参数调用:
- 被传递到的服务发现引用
DNSServiceEnumerateDomains
- 指示是否将立即再次调用您的回调以传递有关已找到的另一个域的信息、是否从应用程序维护的列表中添加或删除此域以及是否将该域作为默认域添加或删除的标志
- 找到域的接口的索引
- 指示枚举是否成功的错误代码;如果枚举成功,则其他参数包含有效数据
- 找到的域的名称
- 传递给的用户定义的上下文信息
DNSServiceEnumerateDomains
运行循环或select
循环将根据每个接口枚举的每个推荐域以及添加或删除域时得到通知。
您负责将守护程序的响应组装到当前推荐域的列表中。
注意:即使标志指示列表已完成,如果添加或删除域、设置为默认值或不再是默认值,您的回调也会再次被调用。
要终止枚举,请从运行循环或select
循环中删除套接字描述符并调用DNSServiceRefDeallocate
,将调用DNSServiceEnumerateDomains
时初始化的服务发现引用传递给它。
服务发现引用无效,与该引用关联的内存被释放。
与mDNSResponder
守护程序连接的基础套接字关闭,从而终止应用程序与守护程序的连接。
六、在Windows中使用DNS服务发现
DNS Service Discovery在编写时考虑到了跨平台兼容性。
因此,所有在OS X和iOS中有效的DNS Service Discovery API调用在Windows中也有效。
这两个平台之间的区别在于每个句柄如何运行循环。
接下来的两节将解释编写利用Windows中的DNS Service Discovery的程序需要进行哪些更改。
在阅读这些部分之前,如果您还没有熟悉DNS Service Discovery API和Microsoft Foundation类,您将希望熟悉它们。
1、Windows图形用户界面
要在Windows图形用户交互界面中正确合并DNS Service Discovery,请使用WinSockWSAAsyncSelect
函数。
WSAAsyncSelect
函数将基于套接字的网络事件集成到Windows消息循环中。
要在Windows代码中使用它,您应该首先创建并初始化一个DNSServiceRef
对象。
然后,调用函数WSAAsyncSelect
将您的DNSServiceRef
对象的套接字与Windows消息循环相关联。
WSAAsyncSelect
需要四个参数:DNSServiceRef
对象的套接字、接收消息的窗口、事件发生时发送的消息以及您感兴趣的网络事件的位掩码。
下面提供了一个简单的示例。
在示例中,您可以看到如何创建NULL
DNSServiceRef
对象,使用DNSServiceBrowse
初始化该引用,然后使用WSAAsyncSelect
将其添加到工作循环。
// create blank DNSServiceRef
e = new ServiceHandlerEntry;
...
// initialize the DNSServiceRef for browsing
err = DNSServiceBrowse( &e->ref, 0, 0, e->type, NULL, BrowseCallBack, e );// add browsing to the work loop with WSAAsyncSelect
// where m_hWnd is the window, WM_PRIVATE_SERVICE_EVENT is the message and
// FD_READ and FD_CLOSE are bitmasks for reading and closing sockets
err = WSAAsyncSelect((SOCKET) DNSServiceRefSockFD(e->ref),m_hWnd,WM_PRIVATE_SERVICE_EVENT,FD_READ|FD_CLOSE);
2、Windows命令行界面
使用DNS服务发现创建Windows命令行程序类似于为OS X或iOS创建命令行程序。
Windows与OS X和iOS一样,支持select
系统调用。
此函数用于确定DNS服务发现API函数的结果何时可用。
有关将select
循环与DNS服务发现一起使用的更多信息,请参阅注册和终止服务、浏览网络服务和解析服务的当前地址。
2024-06-18(二)
相关文章:

Apple - DNS Service Discovery Programming Guide
本文翻译整理自:DNS Service Discovery Programming Guide(更新日期:2013-08-08 https://developer.apple.com/library/archive/documentation/Networking/Conceptual/dns_discovery_api/Introduction.html#//apple_ref/doc/uid/TP30000964 文…...

如何高效地为pip换源:详细操作指南
在Python开发中,pip是我们不可或缺的包管理工具。然而,默认的官方源下载速度较慢,尤其是在国内使用时可能会遇到网络问题。为了提高下载速度,我们可以通过更换国内的镜像源来解决这一问题。本文将详细介绍如何高效地为pip换源&…...

免费ddns工具,快解析DNS解析使用教程
DDNS(Dynamic Domain Name Server),中文叫动态域名解析,主要用于没有固定公网ip的网络环境下,使用一个固定的域名,解析动态变化的ip地址,达到远程访问的目的。 众所周知,目前公网ip资源非常紧缺…...

【Vite】控制打包结构
配置 vite.config.json 文件: import { defineConfig } from "vite";export default defineConfig({// ...build: {rollupOptions: {output: {entryFileNames: "js/[name]-[hash].js",chunkFileNames: "js/[name]-[hash].js",assetF…...

Debian Linux安装minikubekubectl
minikube&kubectl minkube用于在本地开发环境中快速搭建一个单节点的Kubernetes集群,还有k3s,k3d,kind都是轻量级的k8skubectl是使用K8s API 与K8s集群的控制面进行通信的命令行工具 这里使用Debian Linux演示,其他系统安装见官网,首先…...

Discuz动漫二次元风格网站模板
1、本模板为门户论坛个人空间形式,其中个人空间模板需要单独购买,点击购买,美化N多默认模板页面 2、全新设计的标签页,标签页帖子图文调用 3、论坛首页,分区下版块帖子论坛首页自动调用,自带分区图片模式与…...

RIP、OSPF、IS-IS学习
文章目录 前言RIP路由信息协议OSPF开放最短路径优先IS-IS 中间系统到中间系统总结 前言 路由协议的种类繁多,每种协议都有其独特的特性、工作原理和适用场景。本文将重点介绍:RIP(路由信息协议)、OSPF(开放最短路径优…...

移植案例与原理 - build lite源码分析 之 hb命令__main__.py
hb命令可以通过python pip包管理器进行安装,应该是OpenHarmony Build的缩写,在python包名称是ohos-build。hb作为编译构建子系统提供的命令行,用于编译构建产品、芯片厂商组件或者单个组件。本文,我们来学习hb的源码。 1、hb的安…...

Leo赠书活动-26期 不同数据库背后的数据存储方案
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 赠书活动专栏 ✨特色专栏:…...

在Windows10中使用Vim
服务器没有图形界面,但是numpy包又需要调用图形界面接口,这样就导致了错误,搞得我只好先回windows开发。看来当年 Ubuntu桌面版也不算是多此一举啊。 这么多ide我还是喜欢vim,因为它真的太简单了。咱们这个老年机启动的也非常快&…...

【Python机器学习实战】 | 基于PCA主成分分析技术读入空气质量监测数据进行数据预处理并计算空气质量综合评测结果
🎩 欢迎来到技术探索的奇幻世界👨💻 📜 个人主页:一伦明悦-CSDN博客 ✍🏻 作者简介: C软件开发、Python机器学习爱好者 🗣️ 互动与支持:💬评论 &…...

学习java第一百零八天
Spring的AOP理解: OOP面向对象,允许开发者定义纵向的关系,但并不适用于定义横向的关系,会导致大量代码的重复,而不利于各个模块的重用。 AOP,一般称为面向切面,作为面向对象的一种补充ÿ…...

Linux通配符总结
Linux通配符总结 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在Linux系统中,通配符是一种用于匹配文件名或路径名的特殊字符。通过使用通配符&a…...

ffmpeg的安装教程
1.官网下载ffmpeg 进入Download FFmpeg网址,点击下载windows版ffmpeg(点击左下第一个绿色的行) 在release builds第一个绿框里面选择一个版本下载。 2.配置 下载完成后解压该压缩包单击进入ffmpeg\bin,会出现如下界面࿱…...

禅道身份认证绕过漏洞(QVD-2024-15263)复现
禅道项目管理系统在开源版、企业版、旗舰版的部分版本中都存在此安全漏洞。攻击者可利用该漏洞创建任意账号实现未授权登录。 1.漏洞级别 高危 2.漏洞搜索 fofa: title"禅道"3.影响范围 v16.x < 禅道 < v18.12 (开源版) v6.x <…...

深入分析 Android BroadcastReceiver (六)
文章目录 深入分析 Android BroadcastReceiver (六)1. 广播机制的高级优化策略1.1 使用 Sticky Broadcast(粘性广播)示例:粘性广播(过时,不推荐) 1.2 使用 LiveData 和 ViewModel 进行组件通信示例…...

mysql 查询的一般思路
能用单表优先用单表,即便是需要用group by、order by、limit等,效率一般也比多表高 不能用单表时优先用连接,连接是SQL中非常强大的用法,小表驱动大表建立合适索引合理运用连接条件,基本上连接可以解决绝大部分问题。…...

【Web APIs】DOM 文档对象模型 ⑤ ( 获取特殊元素 | 获取 html 元素 | 获取 body 元素 )
文章目录 一、获取特殊元素1、获取 html 元素2、获取 body 元素3、完整代码示例 本博客相关参考文档 : WebAPIs 参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/APIgetElementById 函数参考文档 : https://developer.mozilla.org/zh-CN/docs/Web/API/Document/getE…...

Android11 以Window的视角来看FallbackHome的启动
在WMS中,使用WindowState代表着一个Window并维护着一个Window的"层级树",每个Window需要按照"层级"的规则进行排列。对于FallbackHome,其Window是挂载在home task上,而home task挂载在DefaultTaskDisplayArea…...

9 RestClient客户端操作文档
1. match_all GetMapping("matchAll")public void matchAll() throws IOException {//1. 准备requestSearchRequest request new SearchRequest("hotel");//2. 组织DSL参数request.source().query(QueryBuilders.matchAllQuery());SearchResponse respon…...

『Z-Weekly Feed 08』加密资产观 | FHE应用前景 | OPAL协议
一位机构投资者的加密资产观 作者:Hongbo 01 💡TL;DR 在加密投资领域如何找到真正的“价值”:Crypto 作为一种新兴资产,应该找到一种区别于传统公司股票资产的估值方法,本文重点阐述了加密货币作为新的资产类型与传统资…...

酒店预定系统
酒店预定系统本身设计过程中会遇到售卖系统两个常见问题,第一个同一个房间同一日期被多个订单预定,或者预定和库存数据不一致,这些都会涉及到金钱,需要在系统涉及是被重点考虑。 问题1:同一个房间同一个日期被多个订单预定 酒店…...

Redis的实战常用一、验证码登录(解决session共享问题)(思路、意识)
一、基于session实现登录功能 第一步:发送验证码: 用户在提交手机号后,会校验手机号是否合法: 如果不合法,则要求用户重新输入手机号如果手机号合法,后台此时生成对应的验证码,同时将验证码进行…...

基于Spring Boot的智能分析平台
项目介绍: 智能分析平台实现了用户导入需要分析的原始数据集后,利用AI自动生成可视化图表和分析结论,改善了传统BI系统需要用户具备相关数据分析技能的问题。该项目使用到的技术是SSMSpring Boot、redis、rabbitMq、mysql等。在项目中&#…...

HTML(13)——显示模式
目录 显示模式 块级元素 行内元素 行内块元素 转换显示模式 显示模式:标签的显示方式 作用:布局网页时,根据标签的显示模式选择合适的标签摆放内容 显示模式 块级元素 独占一行宽度默认为父级的100%添加宽高属性生效 行内元素 …...

【Spring】Spring Boot 快速入门
📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更…...

Go自定义数据的序列化流程
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...

贪心算法练习题(2024/6/18)
什么是贪心 贪心的本质是选择每一阶段的局部最优,从而达到全局最优。 贪心算法一般分为如下四步: 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 1分发饼干 假设你是一位很棒的家长,…...

4.1 四个子空间的正交性
一、四个子空间的正交性 如果两个向量的点积为零,则两个向量正交: v ⋅ w v T w 0 \boldsymbol v\cdot\boldsymbol w\boldsymbol v^T\boldsymbol w0 v⋅wvTw0。本章着眼于正交子空间、正交基和正交矩阵。两个子空间的中的向量,一组基中的向…...

RabbitMQ实践——使用WebFlux响应式方式实时返回队列中消息
大纲 Pom.xml监听队列实时返回消息测试完整代码工程代码 在之前的案例中,我们在管理后台收发消息都是通过短连接的形式。本文我们将探索对队列中消息的实时读取,并通过流式数据返回给客户端。 webflux是反应式Web框架,客户端可以通过一个长连…...