NSConnection - как правильно сделать "распутывание" объекта?
Для Mac OSX я пытаюсь использовать NSConnection для прокси-доступа к объекту из одного экземпляра приложения в другой на том же хосте. Соответствующий код ниже. Я могу предоставить больше, если это необходимо. Предположим, когда я говорю "сервер", я имею в виду приложение, которое фактически "продает" объект с NSConnection. И "клиент" - это другой экземпляр того же приложения, которое получает к нему прокси.
Все работает, кроме двух вопросов.
Когда приложение, действующее как сервер, пытается разорвать объект, который оно продает, любой клиент, подключенный через прокси-сервер, остается. То есть даже после того, как я позвоню
stopLocalServer
Приведенная ниже функция позволяет любому клиентскому приложению, которое ранее подключилось и получило прокси-объект, все еще может отправлять сообщения и вызывать код в приложении сервера. Я бы ожидал, что клиент сгенерирует исключение при передаче сообщения после вызова сервераNSConnection:invalidate
, Как принудительно отключить любой клиент, не требуя выхода из процесса сервера?в
startClientConnection
Приведенный ниже код, если сервер никогда не передавал объект в первую очередь с ожидаемым зарегистрированным именем, то вызов клиентаNSConnection:connectionWithRegisteredName:host
немедленно вернет ноль. Это хорошо. Но если сервер начал торговать объектом черезstartLocalServer
код ниже, затем позже перестает продавать егоstopLocalServer
последующие попытки подключения клиента будут зависать (блокироваться навсегда) до тех пор, пока не завершится процесс приложения сервера. Вызов NSConnection:connectionWithRegisteredName возвращает объект, отличный от nil, но вызов[_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;
}
1 ответ
Отвечая на мой собственный вопрос. Я все еще буду ждать лучшего ответа, или, если кто-то сможет сделать лучшую работу, объясняя причины, почему это необходимо.
Я верю 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 выше.