Melhor maneira de fazer comunicação entre processos no Mac OS X

Eu estou olhando para construir um aplicativo Cocoa no Mac com um processo de daemon de back-end (realmente apenas um aplicativo Cocoa principalmente sem cabeça, provavelmente), juntamente com 0 ou mais aplicativos “cliente” rodando localmente (embora se possível eu também gostaria de oferecer suporte a clientes remotos; os clientes remotos seriam apenas outros dispositivos Mac ou iPhone OS).

Os dados que estão sendo comunicados serão bastante triviais, principalmente apenas texto e comandos (que eu acho que podem ser representados como texto de qualquer maneira), e talvez o pequeno arquivo ocasional (uma imagem possivelmente).

Eu olhei alguns methods para fazer isso, mas não tenho certeza do que é “melhor” para a tarefa em mãos. Coisas que eu considerei:

  • Lendo e escrevendo em um arquivo (… sim), muito básico mas não muito escalável.
  • Soquetes puros (eu não tenho experiência com sockets, mas eu pareço pensar que eu posso usá-los para enviar dados localmente e através de uma rede. Embora pareça complicado fazer tudo em Cocoa
  • Objetos Distribuídos: parece bastante deselegante para uma tarefa como esta
  • NSConnection : Eu não consigo descobrir o que esta class ainda faz, mas eu li sobre isso em alguns resultados de busca do IPC

Tenho certeza de que há coisas que estou perdendo, mas fiquei surpreso ao descobrir uma falta de resources sobre esse assunto.

Atualmente estou olhando para as mesmas perguntas. Para mim, a possibilidade de adicionar clientes do Windows mais tarde torna a situação mais complicada; no seu caso, a resposta parece ser mais simples.

Sobre as opções que você considerou:

  1. Arquivos de controle: Embora seja possível se comunicar por meio de arquivos de controle, você deve ter em mente que os arquivos precisam ser comunicados por meio de um sistema de arquivos de rede entre as máquinas envolvidas. Assim, o sistema de arquivos de rede serve como uma abstração da infraestrutura de rede real, mas não oferece a potência e a flexibilidade totais que a rede normalmente possui. Implementação: Praticamente, você precisará ter pelo menos dois arquivos para cada par de clientes / servidores: um arquivo que o servidor usa para enviar uma solicitação ao (s) cliente (s) e um arquivo para as respostas. Se cada processo puder se comunicar das duas maneiras, você precisará duplicar isso. Além disso, tanto o (s) cliente (s) quanto o (s) servidor (es) trabalham em uma base “pull”, ou seja, eles precisam revisitar os arquivos de controle frequentemente e ver se algo novo foi entregue.

    A vantagem dessa solução é que ela minimiza a necessidade de aprender novas técnicas. A grande desvantagem é que tem enormes demandas na lógica do programa; muitas coisas precisam ser atendidas por você (os arquivos serão escritos em uma única parte ou pode acontecer de qualquer parte pegar arquivos inconsistentes? Com ​​que frequência as verificações devem ser implementadas? Preciso me preocupar com o sistema de arquivos, como cache, etc? Posso adicionar criptografia mais tarde sem brincar com coisas fora do código do meu programa? …)

    Se portabilidade era um problema (o que, até onde eu entendi da sua pergunta não é o caso), então essa solução seria fácil de portar para sistemas diferentes e até mesmo diferentes linguagens de programação. No entanto, não conheço nenhum sistema de arquivos de rede para o iPhone OS, mas não estou familiarizado com isso.

  2. Soquetes: A interface de programação é certamente diferente; Dependendo da sua experiência com programação de socket, pode significar que você tem mais trabalho aprendendo primeiro e depurando depois. Implementação : Praticamente, você precisará de uma lógica semelhante à anterior, ou seja, cliente (s) e servidor (es) se comunicando via rede. Uma vantagem definitiva dessa abordagem é que os processos podem funcionar com base em “push”, ou seja, podem escutar em um soquete até chegar uma mensagem que seja superior à verificação regular dos arquivos de controle. Corrupção e inconsistências na rede também não são sua preocupação. Além disso, você (pode) ter mais controle sobre a maneira como as conexões são estabelecidas, em vez de confiar em coisas fora do controle do seu programa (novamente, isso é importante se você decidir adicionar criptografia mais tarde).

    A vantagem é que muitas coisas são tiradas de seus ombros que incomodariam uma implementação em 1. A desvantagem é que você ainda precisa alterar substancialmente sua lógica de programa para ter certeza de que envia e recebe as informações corretas (tipos de arquivo). etc).

    Na minha experiência, a portabilidade (ou seja, a facilidade de transição para diferentes sistemas e até linguagens de programação) é muito boa, já que qualquer coisa, mesmo remotamente compatível com o POSIX, funciona.

    [ EDIT: Em particular, assim que você se comunica números binários endianess se torna um problema e você tem que cuidar desse problema manualmente – este é um caso especial (!) Comum da “informação correta” questão que mencionei acima. Ele vai te morder, por exemplo, quando você tem um PowerPC falando com um Mac Intel. Este caso especial desaparece com a solução 3. + 4. juntos todos os outros problemas de “informação correta”.]

  3. +4. Objetos distribuídos: o cluster de classs NSProxy é usado para implementar objects distribuídos. NSConnection é responsável por configurar conexões remotas como um pré-requisito para o envio de informações, portanto, depois de entender como usar esse sistema, você também entende os objects distribuídos. ; ^)

    A idéia é que sua lógica de programa de alto nível não precisa ser alterada (ou seja, seus objects se comunicam via mensagens e recebem resultados e as mensagens juntas com os tipos de retorno são idênticas àquelas a que você está acostumado) se preocupar com os detalhes da infra-estrutura de rede. Bem, pelo menos em teoria. Implementação: Eu também estou trabalhando nisso agora, então meu entendimento ainda é limitado. Tanto quanto eu entendo, você precisa configurar uma certa estrutura, ou seja, você ainda tem que decidir quais processos (locais e / ou remotos) podem receber quais mensagens; é isso que o NSConnection faz. Neste ponto, você define implicitamente uma arquitetura cliente / servidor, mas não precisa se preocupar com os problemas mencionados em 2.

    Há uma introdução com dois exemplos explícitos no servidor do projeto Gnustep; Ele ilustra como a tecnologia funciona e é um bom ponto de partida para experimentar: http://www.gnustep.org/resources/documentation/Developer/Base/ProgrammingManual/manual_7.html

    Infelizmente, as desvantagens são uma perda total de compatibilidade (embora você ainda esteja bem com a configuração mencionada de Macs e iPhone / iPad apenas) com outros sistemas e perda de portabilidade para outros idiomas. Gnustep com Objective-C é, na melhor das hipóteses, compatível com código, mas não há como se comunicar entre Gnustep e Cocoa, veja minha edição para a questão número 2 aqui: CORBA no Mac OS X (Cocoa)

    [ EDIT: Acabei de me deparar com outra informação que desconhecia. Embora tenha verificado que o NSProxy está disponível no iPhone, não verifiquei se as outras partes do mecanismo de objects distribuídos estão. De acordo com este link: http://www.cocoabuilder.com/archive/cocoa/224358-big-picture-relationships-between-nsconnection-nsinputstream-nsoutputstream-etc.html (pesquise a página pela frase “iPhone OS”) eles não são. Isso excluiria essa solução se você exigir usar o iPhone / iPad neste momento.]

Portanto, para concluir, existe um trade-off entre o esforço de aprendizagem (e implementação e debugging) de novas tecnologias, por um lado, e a codificação manual de lógica de comunicação de nível inferior, por outro. Enquanto a abordagem de object distribuído toma a maior parte de seus ombros e incorre nas menores mudanças na lógica do programa, é o mais difícil de aprender e também (infelizmente) o menos portátil.

Isenção de responsabilidade: Objetos distribuídos não estão disponíveis no iPhone .


Por que você acha objects distribuídos deselegantes? Eles soam como um bom jogo aqui:

  • ordenação transparente de tipos fundamentais e classs Objective-C
  • não importa realmente se os clientes são locais ou remotos
  • pouco trabalho adicional para aplicativos baseados em Cocoa

A documentação pode parecer mais trabalho do que realmente é, mas tudo o que você basicamente precisa fazer é usar os protocolos de forma limpa e exportar, ou conectar-se respectivamente, ao object raiz do servidor.
O resto deve acontecer automagicamente nos bastidores para você no cenário dado.

Estamos usando ThoMoNetworking e funciona bem e é rápido para configuração. Basicamente, ele permite que você envie objects compatíveis com NSCoding na rede local, mas obviamente também funciona se o cliente e o servidor estiverem na mesma máquina. Como um wrapper em torno das classs de fundação, cuida do emparelhamento, reconexões, etc.