Il modo migliore per fare comunicazione tra processi su Mac OS X

Sto cercando di creare un’applicazione Cocoa su Mac con un processo demone back-end (probabilmente solo un’app Cocoa perlopiù senza testa, probabilmente), insieme a 0 o più applicazioni “client” in esecuzione localmente (anche se, se ansible, avrei piace supportare anche i client remoti, i client remoti sarebbero sempre solo altri Mac o dispositivi iPhone OS).

I dati comunicati saranno abbastanza banali, per lo più solo testo e comandi (che suppongo possano essere comunque rappresentati come testo), e forse il piccolo file occasionale (un’immagine possibilmente).

Ho esaminato alcuni metodi per farlo, ma non sono sicuro di quale sia il “migliore” per l’attività in corso. Cose che ho considerato:

  • Leggere e scrivere su un file (… sì), molto semplice ma non molto scalabile.
  • Prese pure (non ho esperienza con le prese ma mi sembra di pensare di poterle usare per inviare dati localmente e attraverso una rete, anche se sembra complicato se si fa tutto in Cocoa
  • Oggetti distribuiti: sembra piuttosto inelegante per un’attività come questa
  • NSConnection : Non riesco davvero a capire cosa faccia questa class, ma ne ho letto in alcuni risultati di ricerca IPC

Sono sicuro che ci sono cose che mi mancano, ma sono stato sorpreso di trovare una mancanza di risorse su questo argomento.

Attualmente sto esaminando le stesse domande. Per me la possibilità di aggiungere client Windows in seguito rende la situazione più complicata; nel tuo caso la risposta sembra essere più semplice.

Informazioni sulle opzioni che hai considerato:

  1. File di controllo: mentre è ansible comunicare tramite i file di controllo, è necessario tenere presente che i file devono essere comunicati tramite un file system di rete tra le macchine coinvolte. Quindi il file system di rete funge da astrazione dell’infrastruttura di rete effettiva, ma non offre la piena potenza e flessibilità che la rete normalmente possiede. Implementazione: in pratica, è necessario disporre di almeno due file per ogni coppia di client / server: un file che il server utilizza per inviare una richiesta ai client e un file per le risposte. Se ogni processo può comunicare in entrambi i modi, è necessario duplicarlo. Inoltre, sia il client (s) e il server (s) lavorano su una base “pull”, cioè, hanno bisogno di rivedere i file di controllo di frequente e vedere se qualcosa di nuovo è stato consegnato.

    Il vantaggio di questa soluzione è che riduce al minimo la necessità di apprendere nuove tecniche. Il grosso svantaggio è che ha enormi esigenze sulla logica del programma; un sacco di cose devono essere curate da te (i file saranno scritti in un unico pezzo o può accadere che ogni parte raccolga file incoerenti? Con quale frequenza dovrebbero essere implementati i controlli? Devo preoccuparmi del file system, come la memorizzazione nella cache, ecc. Posso aggiungere la crittografia in un secondo momento senza dover gironzolare con cose al di fuori del mio codice di programma? …)

    Se la portabilità fosse un problema (che, per quanto ho capito dalla tua domanda non è il caso), allora questa soluzione sarebbe facile da portare a sistemi diversi e persino a linguaggi di programmazione diversi. Tuttavia, non conosco alcun file di rete per iPhone OS, ma non mi è familiare.

  2. Prese: l’interfaccia di programmazione è sicuramente diversa; a seconda della tua esperienza con la programmazione di socket, potresti voler dire che hai più lavoro per impararlo prima e debuggarlo in seguito. Implementazione : in pratica, avrete bisogno di una logica simile come prima, cioè client (s) e server (s) che comunicano tramite la rete. Un ulteriore vantaggio di questo approccio è che i processi possono funzionare su una base “push”, cioè, possono essere ascoltati su un socket fino a quando arriva un messaggio che è superiore alla verifica regolare dei file di controllo. Anche la corruzione e le incoerenze della rete non ti interessano. Inoltre, potresti avere (potresti) maggiore controllo sul modo in cui vengono stabilite le connessioni piuttosto che affidarti a cose al di fuori del controllo del tuo programma (anche in questo caso è importante se decidi di aggiungere la crittografia in un secondo momento).

    Il vantaggio è che molte cose ti vengono tolte dalle spalle che potrebbero infastidire un’implementazione in 1. Lo svantaggio è che devi ancora modificare sostanzialmente la logica del tuo programma per assicurarti di inviare e ricevere le informazioni corrette (tipi di file eccetera.).

    Nella mia esperienza la portabilità (ad esempio, la facilità di transizione verso sistemi diversi e persino i linguaggi di programmazione) è molto buona poiché tutto ciò che è remotamente compatibile con POSIX funziona.

    [ MODIFICA: In particolare, non appena comunichi numeri binari, l’endianità diventa un problema e devi risolvere questo problema manualmente – questo è un caso comune (!) Speciale del problema “informazione corretta” che ho menzionato sopra. Ti morderà ad esempio quando hai un PowerPC che parla con un Mac Intel. Questo caso speciale scompare con la soluzione 3. + 4. insieme faranno tutti gli altri problemi di “informazione corretta”.]

  3. +4. Oggetti distribuiti: il cluster di class NSProxy viene utilizzato per implementare oggetti distribuiti. NSConnection è responsabile per l’impostazione delle connessioni remote come prerequisito per l’invio di informazioni in giro, quindi una volta compreso come utilizzare questo sistema, capisci anche gli oggetti distribuiti. ; ^)

    L’idea è che la logica del tuo programma di alto livello non debba essere modificata (ad esempio, gli oggetti comunicano tramite messaggi e ricevono risultati e i messaggi insieme ai tipi di reso sono identici a quelli a cui sei abituato dall’implementazione locale) senza dover preoccuparsi dei dettagli dell’infrastruttura di rete. Bene, almeno in teoria. Implementazione: sto lavorando anche a questo adesso, quindi la mia comprensione è ancora limitata. Per quanto ho capito, è necessario impostare una determinata struttura, ovvero, è ancora necessario decidere quali processi (locali e / o remoti) possono ricevere quali messaggi; questo è ciò che fa NSConnection . A questo punto, definisci implicitamente un’architettura client / server, ma non devi preoccuparti dei problemi menzionati in 2.

    C’è un’introduzione con due esempi espliciti sul server di progetto Gnustep; illustra come funziona la tecnologia ed è un buon punto di partenza per sperimentare: http://www.gnustep.org/resources/documentation/Developer/Base/ProgrammingManual/manual_7.html

    Sfortunatamente, gli svantaggi sono una perdita totale di compatibilità (anche se continuerai a funzionare bene con la configurazione che hai menzionato solo per Mac e iPhone / iPad) con altri sistemi e perdita di portabilità in altre lingue. Gnustep con Objective-C è al massimo compatibile con il codice, ma non c’è modo di comunicare tra Gnustep e Cocoa, vedi la mia modifica alla domanda numero 2 qui: CORBA su Mac OS X (Cocoa)

    [ EDIT: ho appena trovato un’altra informazione di cui non ero a conoscenza. Mentre ho controllato che NSProxy sia disponibile su iPhone, non ho controllato se le altre parti del meccanismo degli oggetti distribuiti lo sono. Secondo questo link: http://www.cocoabuilder.com/archive/cocoa/224358-big-picture-relationships-between-nsconnection-nsinputstream-nsoutputstream-etc.html (cerca nella pagina la frase “iPhone OS”) non sono. Questo escluderebbe questa soluzione se richiedi di utilizzare iPhone / iPad in questo momento.]

Quindi, per concludere, c’è un compromesso tra lo sforzo di apprendimento (e l’implementazione e il debug) delle nuove tecnologie da un lato e la logica di comunicazione di livello inferiore a livello manuale dall’altro. Mentre l’approccio ad oggetti distribuiti prende la maggior parte del carico delle spalle e incorre nei più piccoli cambiamenti nella logica del programma, è il più difficile da imparare e anche (sfortunatamente) il meno portabile.

Dichiarazione di non responsabilità: gli oggetti distribuiti non sono disponibili su iPhone .


Perché trovi oggetti distribuiti ineleganti? Sembra una buona partita qui:

  • marshalling trasparente di tipi fondamentali e classi Objective-C
  • non importa se i client sono locali o remoti
  • non molto lavoro aggiuntivo per le applicazioni basate su Cocoa

La documentazione potrebbe far sembrare più lavoro di quanto non sia in realtà, ma tutto ciò che devi fare in pratica è usare i protocolli in modo pulito ed esportarli, o collegarti rispettivamente, all’object root del server.
Il resto dovrebbe accadere automagicamente dietro le quinte per te nello scenario dato.

Stiamo usando ThoMoNetworking e funziona bene ed è veloce da configurare. Fondamentalmente consente di inviare oggetti conformi a NSCoding nella rete locale, ma ovviamente funziona anche se client e server sono sullo stesso computer. Come wrapper per le classi base, si occupa dell’accoppiamento, riconnessione, ecc.