NSConnection - 如何正确地做"展开"一个物体?

时间:2015-07-05 02:05:13

标签: objective-c macos distributed-objects nsconnection

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

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

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

  2. 在下面的startClientConnection代码中,如果服务器从未在第一个位置使用预期的注册名称销售对象,则客户端对NSConnection:connectionWithRegisteredName:host的调用将立即返回nil。这很好。但是,如果服务器已经开始通过下面的startLocalServer代码销售对象,然后停止使用stopLocalServer将其自动销售,则后续客户端尝试连接将挂起(永久阻止),直到服务器应用程序进程退出。对NSConnection的调用:connectionWithRegisteredName返回一个非零对象,但对[_clientConnection rootProxy]的调用将一直挂起,直到服务器应用程序实际退出。

  3. 我怀疑我没有正确拆除原来的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;
    }
    

1 个答案:

答案 0 :(得分: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。