在Delphi 7中有效的ZeroConf / Bonjour代码在2009年无法正常工作

Del*_*ics 4 delphi bonjour zeroconf delphi-2009

我对DNSServiceRegister具有以下声明:

  function DNSServiceRegister
      (
      var sdRef: TDNSServiceRef;
      const flags: TDNSServiceFlags;
      const interfaceIndex: uint32_t;
      const name: PUTF8String;                    //* may be NULL */
      const regType: PUTF8String;
      const domain: PUTF8String;                  //* may be NULL */
      const host: PUTF8String;                    //* may be NULL */
      const port: uint16_t;
      const txtLen: uint16_t;
      const txtRecord: Pointer;                 //* may be NULL */
      const callBack: TDNSServiceRegisterReply; //* may be NULL */
      const context: Pointer                    //* may be NULL */
      ): TDNSServiceErrorType; stdcall; external DNSSD_DLL;
Run Code Online (Sandbox Code Playgroud)

在我的Bonjour框架中,对于已启用的已宣布服务(即实际上开始通过Bonjour宣布自身),我有以下响应:

  procedure TAnnouncedService.Activate;
  var
    flags: Cardinal;
    name: UTF8String;
    svc: UTF8String;
    pn: PUTF8String;
    ps: PUTF8String;
  begin
    fPreAnnouncedServiceName := ServiceName;

    inherited;

    if AutoRename then
      flags := 0
    else
      flags := kDNSServiceFlagsNoAutoRename;  { - do not auto-rename }

    if (ServiceName <> '') then
    begin
      name  := ServiceName;
      pn    := PUTF8String(name);
    end
    else
      pn := NIL;

    svc := ServiceType;
    ps  := PUTF8String(svc);

    CheckAPIResult(DNSServiceRegister(fHandle,
                                      flags,
                                      0 { interfaceID - register on all interfaces },
                                      pn,
                                      ps,
                                      NIL { domain - register in all available },
                                      NIL { hostname - use default },
                                      ReverseBytes(Port),
                                      0   { txtLen },
                                      NIL { txtRecord },
                                      DNSServiceRegisterReply,
                                      self));
    TBonjourEventHandler.Create(fHandle);
  end;
Run Code Online (Sandbox Code Playgroud)

这比我严格认为的要冗长得多,当然,它在Delphi 7中以不那么冗长的形式运行得很好。我已经将许多操作扩展为显式步骤,以方便调试,例如,能够识别在Delphi 2009中“幕后”发生的字符串有效负载的任何隐式转换。

即使以这种不整洁的扩展形式,该代码也可以在Delphi 7中编译并完美地工作,但是如果我在Delphi 2009中进行编译和运行,则不会收到有关我的服务的公告。

例如,如果我将此代码作为Delphi 7应用程序的一部分运行以注册_daap._tcp服务(iTunes共享库),则会在运行的iTunes实例中看到它的弹出窗口。如果我重新编译完全相同的应用,无需修改在2009年德尔福并运行它,我也没有看到出现在我的iTunes服务。

使用dns-sd命令行实用程序进行监视时,我得到相同的行为。也就是说,用Delphi 7编译的服务代码的行为与我期望的一样,是在Delphi 2009中编译的-没有任何行为。

我没有从Bonjour API中收到任何错误-DNSServiceRegisterReply回调正在使用ErrorCode为0(零)(即成功)进行调用,即如果提供了在标志中指定了AutoRename的NIL名称参数,则为我的服务分配了正确的默认名称。但是,该服务仍未在iTunes中显示。

我对正在发生的事情一无所知。

从代码的扩展中可以看出,我一直在追寻Delphi 2009中Unicode实现引入的潜在错误,但这似乎无济于事。

该代码最初是根据Bonjour API / SDK的1.0.3版本开发的。此后,我已将其更新为1.0.6,以防万一涉及其中,但未成功。afaict 1.0.6仅添加了一个用于获取“属性”的新功能,该功能目前仅支持用于获取Bonjour版本的“ DaemonVersion”属性-效果很好。

注意:我知道,目前的代码在Delphi 7中从技术上讲不是UTF8安全的-我已尽可能地消除了显式转换,以使Delphi 2009应用的自动转换尽可能简单。我现在的目标是使它在Delphi 2009中工作,然后从该解决方案开始逐步发展,以期找到与早期版本的Delphi兼容的方法。

注意:此外,我最初在浏览广告服务时也遇到了问题,例如,在网络上确定实际的iTunes共享库。这些问题是由Delphi 2009中的Unicode处理引起的,现已解决。我的Delphi 2009代码同样可以识别实际的iTunes共享库并查询其TXT记录。仅此服务注册不起作用。

我一定想念一些愚蠢而明显的东西。

有人有任何想法吗?

更新

回到这个问题后,我现在发现了以下内容:

如果我打开了D2009之前的版本和D2009 + IDE(例如D2006和D2010),并且同一个项目同时加载到两个IDE中:

  • 在2006年下构建并运行:可以运行-iTunes收到了我的服务公告
  • 切换到D2010并运行(不构建):它只需进行最少的编译,运行和运行。
  • 在D2010中进行全面构建:它将停止工作

  • 切换回D2006并运行(不构建):不起作用

  • 在D2006中进行全面构建:它可以再次工作

这会给任何其他想法吗?

Del*_*ics 5

答案是令人难以置信。一方面,我犯了一个完全愚蠢,非常简单的错误,但另一方面,就我所知,它永远都不能在任何版本的Delphi中使用!

该问题与任何字符串的Unicode /非Unicode无关,但实际上是由于PORT参数中的类型不匹配。

我正在传递ReverseBytes(Port)的结果-该参数期望一个uint16_t,即Word值。但是,我的Port属性被(惰性地)声明为Integer

一旦修复此问题并将Port声明为Word,它现在就可以在Delphi的D2007-和D2009 +版本中使用。

很奇怪。

我只能认为,当引入Unicode支持时,可能会在某种程度上影响了编译器的其他一些极端情况下的行为已被更改。