NSConnection - 如何正确执行对象的 "unvending"?

NSConnection - how to properly do "unvending" of an object?

对于 Mac OSX,我正在尝试使用 NSConnection 来代理从一个应用程序实例到同一主机上另一个应用程序实例的对象访问。相关代码如下。如果需要,我可以提供更多。假设当我说 "server" 时,我指的是实际上 "vends" 具有 NSConnection 的对象的应用程序。 "client" 是同一应用程序的另一个实例,它获得了它的代理。

一切正常,除了两个问题。

  1. 当充当服务器的应用程序试图拆除它正在出售的对象时,通过代理连接的任何客户端仍然存在。也就是说,即使在我调用下面的 stopLocalServer 函数之后,之前连接并获得代理对象的任何客户端应用程序仍然能够在服务器应用程序上发送消息和调用代码。我本来希望客户端在服务器调用 NSConnection:invalidate 后传递消息时抛出异常。如何在不要求服务器进程退出的情况下强行断开任何客户端?

  2. 在下面的 startClientConnection 代码中,如果服务器一开始就没有使用预期的注册名称出售对象,那么客户端对 NSConnection:connectionWithRegisteredName:host 的调用将立即 return 零。这很好。但是,如果服务器通过下面的 startLocalServer 代码开始销售一个对象,然后停止使用 stopLocalServer 销售它,后续客户端连接尝试将挂起(永远阻塞),直到服务器应用程序进程退出。对 NSConnection:connectionWithRegisteredName return 的调用是一个非零对象,但对 [_clientConnection rootProxy] 的调用将永远挂起,直到服务器应用程序实际退出。

我怀疑我没有正确地拆除原始的 NSConnection 对象,或者我在这里遗漏了一些基本的东西。

这是我的用户界面代码所在平台的一些相关代码:

-(void)startLocalServer:(NSString*)str
{
    [self stopLocalServer];  // clean up any previous instance that might be running
    _serverConnection = [NSConnection new];
    [_serverConnection setRootObject:self];
    [_serverConnection registerName:str];
}
-(void)stopLocalServer
{
    [_serverConnection registerName:nil];
    [_serverConnection setRootObject:nil];
    [_serverConnection invalidate];
    _serverConnection = nil;
}

-(void)startClientConnection:(NSString*)str
{
    [self stopClientConnection];  // tear down any previous connection

    _clientConnection = [NSConnection connectionWithRegisteredName:str host:nil];

    if ((_clientConnection == nil) || (_clientConnection.valid == NO))
    {
        LogEvent(@"ERROR - _clientConnection is nil or invalid!");
    }
    else
    {
        _proxy = [_clientConnection rootProxy];
    }
}

-(void)stopClientConnection
{
    _proxy = nil;
    [_clientConnection invalidate];
    _clientConnection = nil;
}

回答我自己的问题。我仍然会等待更好的答案,或者如果有人能更好地解释为什么需要这样做的原因。

我认为 stopLocalServer 函数需要调用 [[_serverConnection receivePort] invalidate] 以关闭使用连接创建的端口。只需将该行添加到原始 stopLocalServer 函数即可解决我的问题。这会阻止进一步的连接尝试和消息成功。

更恰当地说,应用程序调用可以只拥有 NSConnection 使用的端口。所以这成为启动和停止分布式对象侦听器的更好解决方案:

-(void)startLocalServer:(NSString*)str
{
    [self stopLocalServer];  // clean up any previous instance that might be running
    _port = [NSPort port];   // _port is of type NSPort*
    _serverConnection = [NSConnection connectionWithReceivePort:_port sendPort:nil];
    [_serverConnection setRootObject:self];
    [_serverConnection registerName:str];
}


-(void)stopLocalServer
{
    [_serverConnection registerName:nil];
    [_serverConnection setRootObject:nil];
    [_serverConnection invalidate];
    _serverConnection = nil;

    [_port invalidate];
    _port = nil;
}

这似乎解决了上面的#1 和#2。