2

对于 Mac OSX,我正在尝试使用 NSConnection 代理从一个应用程序实例到同一主机上的另一个应用程序实例的对象访问。相关代码如下。如果需要,我可以提供更多。假设当我说“服务器”时,我指的是实际使用 NSConnection 来“销售”对象的应用程序。而“客户端”是获得代理的同一应用程序的另一个实例。

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

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

  2. 在下面的startClientConnection代码中,如果服务器从一开始就没有使用预期的注册名称出售对象,那么客户端上的调用NSConnection:connectionWithRegisteredName:host将立即返回 nil。这很好。但是,如果服务器通过startLocalServer下面的代码开始出售一个对象,然后用 停止出售它stopLocalServer,随后的客户端连接尝试将挂起(永远阻塞),直到服务器应用程序进程退出。对 NSConnection:connectionWithRegisteredName 的调用返回一个非零对象,但对 的调用[_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;
}
4

1 回答 1

0

回答我自己的问题。我仍然会坚持一个更好的答案,或者是否有人可以更好地解释为什么需要这样做的原因。

我相信该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。

于 2015-07-05T09:32:17.683 回答