Objective c N连接-如何正确地进行“连接”;“不变的”;物体的形状?
对于MacOSX,我尝试使用NSConnection代理同一主机上从一个应用程序实例到另一个应用程序实例的对象访问。相关代码如下。如果需要,我可以提供更多。假设当我说“服务器”时,我指的是实际“出售”具有NSConnection的对象的应用程序。“客户机”是同一应用程序的另一个实例,它向该应用程序获取代理 除了两个问题外,一切正常Objective c N连接-如何正确地进行“连接”;“不变的”;物体的形状?,objective-c,macos,distributed-objects,nsconnection,Objective C,Macos,Distributed Objects,Nsconnection,对于MacOSX,我尝试使用NSConnection代理同一主机上从一个应用程序实例到另一个应用程序实例的对象访问。相关代码如下。如果需要,我可以提供更多。假设当我说“服务器”时,我指的是实际“出售”具有NSConnection的对象的应用程序。“客户机”是同一应用程序的另一个实例,它向该应用程序获取代理 除了两个问题外,一切正常 当充当服务器的应用程序试图拆除它正在出售的对象时,通过代理连接的任何客户端仍然保留。也就是说,即使在我调用下面的stopLocalServer函数之后,以前连接并获得
stopLocalServer
函数之后,以前连接并获得代理对象的任何客户端应用程序仍然能够发送消息并调用服务器应用程序上的代码。在服务器调用NSConnection:invalidate
后传递消息时,我希望客户端会抛出异常。如何在不要求服务器进程退出的情况下强制断开任何客户端startClientConnection
代码中,如果服务器从未使用预期的注册名称出售对象,那么对客户端的NSConnection:connectionWithRegisteredName:host的调用将立即返回nil。这很好。但是,如果服务器已开始通过下面的startLocalServer
代码出售对象,然后稍后停止使用stopLocalServer
出售对象,则后续客户端连接尝试将挂起(永久阻止),直到服务器应用程序进程退出。对NSConnection:connectionWithRegisteredName的调用返回一个非nil对象,但对[\u clientConnection rootProxy]
的调用将永远挂起,直到服务器应用程序实际退出
-(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
函数需要调用[[[u 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问题。为了使客户端不会像您所描述的那样挂起,通常会设置一个超时,这可能与观察者相关,例如
NSConnectionDidDieNotification
。好主意。在生产代码中,超时和try/catch块都是使用NSConnection代码所必须的。超时无法解决问题。但我想我找到了一个满足#1和#2的答案。就我个人而言,我会先让连接失效,然后让端口失效。从连接下面使端口失效似乎是个坏主意。另外,请注意,-registerName:
的文档指出,只有基于NSSocketPort
的连接支持注销。另一种方法可能是使用NSConnectionDelegate
方法加上观察NSConnectionDidDieNotification
来跟踪从连接生成的子连接,并在停止服务器时使这些子连接失效。