Envoyer un message entre 2 Macs

apocaalypsoapocaalypso Membre
juillet 2009 modifié dans API AppKit #1
Bonjour,

Après m'être adonné à  la programmation iPhone, je débute la programmation Mac et biensûr cela me pose quelques problèmes.
Je voudrais envoyer un message quelconque entre deux Macs par l'intermédiaire de mon application. C'est à  dire que les deux Macs lancent l'application et l'un envoie un message à  l'autre. Peut-être par Bluetooth ?
Mais je ne sais absolument pas vers où m'orienter, quelqu'un saurait m'aiguiller ?

Merci d'avance !

Réponses

  • AliGatorAliGator Membre, Modérateur
    23:59 modifié #2
    Regarde du côté des sockets. Tu as un Networking Programming Guide sur les communications réseau dans la doc Apple, et des SampleCodes aussi il me semble. C'est le plus adapté pour faire communiquer 2 machines par réseau.

    Après tu as d'autres solutions sans doute, qui se basent au final un peu dessus au final. C'est pour un besoin spécifique ? Ou tu veux pouvoir envoyer tout et n'importe quoi ?
  • apocaalypsoapocaalypso Membre
    23:59 modifié #3
    Merci Ali !
    En fait tout ce passe par l'application ouverte sur les 2 Macs.
    Non, je veux seulement envoyer du texte et au pire une image.
  • apocaalypsoapocaalypso Membre
    23:59 modifié #5
    Merci pour le lien Ali.
    Si j'utilise Bonjour c'est bon ?
  • AliGatorAliGator Membre, Modérateur
    23:59 modifié #6
    Bonjour ne permet que de faire le discovery, c'est à  dire d'annoncer la présence de ton service sur le réseau d'un côté, et d'en être averti de l'autre. Il ne se charge pas du transfert de données.

    Donc c'est un complément, qui peut être sympa et pratique, mais n'est pas indispensable pour faire communiquer 2 machines. Bonjour permet à  2 machines de se découvrir et savoir qu'elles peuvent communiquer ensemble via le même langage (protocole) mais ne fournit pas de moyen de communiquer à  proprement parler.


    En gros :
    • Un de tes macs annonce qu'il fournit le service toto (exemples non exhaustifs de services : "serveur FTP" ou "serveur Web", ...ou si c'est une imprimante elle peut annoncer "je sais imprimer"... y'a des services types standardisés, sinon rien ne t'empêche d'en utiliser un arbitraire propre à  ton truc genre "Service Toto")
    • Un autre mac qui veut se connecter à  un service Toto, va déjà  chercher s'il existe un "Service Toto" sur le réseau, et t'informer de ceux qu'il a trouvé (ceux qui se sont annoncés comme précedemment)
    • Une fois qu'il a trouvé tous les "Services Toto" disponibles sur le réseau, tu peux demander (encore à  Bonjour) "bon et pour contacter cette machine, enfin ce service en particulier qui me propose "Service Toto", je fais comment ?" et Bonjour va te donner en retour l'adresse IP et le port sur lequel est publié ce service.
    Exemple type :
    - tu as sur ton réseau plusieurs imprimantes compatibles Bonjour (la plupart le sont aujourd'hui il me semble d'ailleurs). Une que tu auras nommée "Imprimante Couleur", l'autre "Imprimante N&B", la 3e "Imprimante Salon", par exemple .
    - tu es sur ton mac et tu veux imprimer. Bah ton logiciel va demander à  Bonjour "liste moi tous les trucs sur le réseau qui proposent le service "_printer._tcp" (printer est le type correspondant au service d'impression, tu l'auras compris).
    - Bonjour va te répondre en listant les 3 imprimantes sus-citées, donc il va te dire : ok j'ai trouvé 3 imprimantes qui s'annoncent sur le réseau : "Imprimante Couleur", "Imprimante N&B" et "Imprimante Salon".
    - Du coup toi tu lui dis "bon ok, je veux utiliser "Imprimante Salon". Et Bonjour va te répondre "ok, pour la contacter utilise l'IP 10.0.2.103 sur le port 27 (par exemple).

    Mais après c'est tout ce que fait Bonjour.
    Une fois que tu as l'IP et le port, faut toujours que tu contactes l'imprimante pour communiquer avec elle (lui envoyer les données à  imprimer, etc).

    Conclusion :
    1) Si tu connais déjà  par coeur l'IP de l'imprimante et le port sur laquelle la contacter, pas besoin de Bonjour. Dans ton cas si tu connais l'IP de ton 2e mac et le port sur lequel il est en attente de connections entrante, pas besoin de Bonjour
    2) Dans tous les cas, Bonjour ou pas, il te faudra mettre en place un canal de communication pour dialoguer entre les 2 ordniateurs. On utilise pour ça les sockets. Un socket sur chaque mac, un sur un mac qui écoute sur un port réseau donné (par exemple ton premier mac, ayant l'IP 10.0.0.1, sur lequel tu crées un socket que tu mets en écoute = attente de connection sur le port 1300), c'est le "serveur", et sur l'autre mac (ça sera le "client") un autre socket qui va aller se connecter sur 10.0.0.1:1300. Une fois que la connection est réalisée, l'un ou l'autre des sockets peut envoyer des données au socket se trouvant à  l'autre bout (donc envoyer des données à  l'autre mac), et l'autre peut vérifier la présence de données sur le socket et les lire le cas échéant.


    Voilà  pour les principes de base. Donc oui tu peux utiliser Bonjour, mais peut-être dans un 2e temps, quand tu maà®triseras les sockets, pour ne pas risquer de tous mélanger.
    Ou sinon dans les SampleCodes d'Apple tu as un exemple PictureSharing (qui fait office de "serveur") et PictureSharingBrowser (qui fait office de "client" et va se connecter sur le serveur pour lui demander de lui envoyer l'image), qui montre conjointement l'utilisation de Bonjour ET des Sockets. Mais c'est un peu "dangereux" comme exemple dans le sens où tu as tout d'un coup, pour débuter si t'as jamais manipuler les sockets c'est pas forcément le plus idéal.

    Note aussi qu'en Cocoa tu as les NSFileHandle qui savent encapsuler des "fileDescriptors" décrivant des sockets (et non des "fichiers" au sens commun du terme), ce qui fait que tu peux utiliser NSFileHandler pour manipuler tes sockets. Ca a pas mal d'avantages, en particulier te simplifie la vie au niveau des écoutes de connections ou de données entrantes, puisque tu peux demander à  ton NSFileHandler de se mettre en écoute en tâche de fond et de t'envoyer une notification quand une connection ou des données arrivent. Du coup t'as plus grand chose à  faire du côté du code "bas niveau" (ça tu peux le voir dans ledit SampleCode à  la limite mais bon lis plutôt les Programming Guides d'abord et les docs sur les sockets sur le net)
  • apocaalypsoapocaalypso Membre
    23:59 modifié #7
    Merci beaucoup Ali, c'est super sympa de m'expliquer aussi longuement !
    Je vais finalement m'aider du PictureSharing et du PictureSharingBrowser, si je peux envoyer des images je pourrai largement envoyer du texte, merci beaucoup de m'avoir expliquer tout ça  ;)
  • Nebuchad34Nebuchad34 Membre
    23:59 modifié #8
    J'en profite pour remercier aussi car j'allais pas tarder à  poster un sujet similaire.

    Avoir une réponse aussi précise à  une question que l'on a pas encore posée, ce devrait être ça l'avenir de OSX-Dev  ;D

    Vraiment, c'est expliqué de manière très compréhensive, chapeau monsieur le gourou Cocoa. o:)
  • yoannyoann Membre
    23:59 modifié #9
    Vous pouvez aussi regarder les objet distribué pour faire communiqué deux machines, l'avantage de cette méthode c'est que vous partagez directement l'accès à  un objet en mémoire sur une machine aux autres, c'est l'inconvénient aussi, quand vous appelez un DO depuis un client, tout est lu dans la mémoire du serveur, donc ne pas oublier de faire des copy si on veut de la persistance.

    ça a l'avantage de simplifier l'aspect réseau et tout ce qui est gestion des socket.

    Par contre je ne saurais dire ce qui est le plus simple a appréhender pour quelqu'un qui n'a joué ni avec l'un ni avec l'autre.
  • apocaalypsoapocaalypso Membre
    23:59 modifié #10
    Oui, c'est pour ça que je me suis inspiré des sockets du PictureSharing.
    Merci pour vos réponses !
  • apocaalypsoapocaalypso Membre
    23:59 modifié #11
    J'ai rencontrer un petit problème, non pas pour envoyer une image, ce que j'ai réussi à  faire mais pour envoyer du texte.
    Pour mon code concernant l'envoie d'image j'ai :
    - (void)connectionReceived:(NSNotification *)aNotification {<br />&nbsp; &nbsp; NSFileHandle * incomingConnection = [[aNotification userInfo] objectForKey:NSFileHandleNotificationFileHandleItem];<br />&nbsp; &nbsp; NSData * representationToSend = [[imageView image] TIFFRepresentation];<br />&nbsp; &nbsp; [[aNotification object] acceptConnectionInBackgroundAndNotify];<br />&nbsp; &nbsp; [incomingConnection writeData:representationToSend];<br />&nbsp; &nbsp; [incomingConnection closeFile];<br />}<br />
    


    Pour mon envoie de texte j'ai donc fait :
    - (void)connectionReceived:(NSNotification *)aNotification {<br />	NSString *message = [textField stringValue];<br />&nbsp; &nbsp; NSFileHandle * incomingConnection = [[aNotification userInfo] objectForKey:NSFileHandleNotificationDataItem];<br />&nbsp; &nbsp; NSData * representationToSend = [message dataUsingEncoding:NSASCIIStringEncoding];<br />&nbsp; &nbsp; [[aNotification object] acceptConnectionInBackgroundAndNotify];<br />&nbsp; &nbsp; [incomingConnection writeData:representationToSend];<br />&nbsp; &nbsp; [incomingConnection closeFile];
    


    Et pour la réception du texte :
    - (void)readAllTheData:(NSNotification *)note {<br />	NSString *theText = [[NSString alloc] initWithData:[[note userInfo] objectForKey:NSFileHandleNotificationDataItem] encoding:NSASCIIStringEncoding];<br />&nbsp; &nbsp; [textView insertText:theText];<br />&nbsp; &nbsp; [theText release];<br />&nbsp; &nbsp; [[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleReadToEndOfFileCompletionNotification object:[note object]];<br />&nbsp; &nbsp; [[note object] release];<br />}
    


    Texte que j'essaye d'insérer dans un textField. Mais le texte est NULL, pourant j'ai fait à  peu près comme pour le code d'envoie d'image.
    Quelqu'un pourrait-il m'éclairer ?

    Merci d'avance !
  • yoannyoann Membre
    23:59 modifié #12
    Tu as vérifié que [[note userInfo] objectForKey:NSFileHandleNotificationDataItem] existe ?
  • apocaalypsoapocaalypso Membre
    23:59 modifié #13
    Et ben lorsque je fais :
    NSLog(&quot;%@&quot;, [[note userInfo] objectForKey:NSFileHandleNotificationDataItem]);
    


    ça me renvoie plein de chiffres et lettres entre 2 signes : <> pour mon code d'envoie mais dans le code de réception la data ne renvoie que <>. Donc j'imagine qu'il n'existe pas de l'autre côté mais je ne comprend pas pourquoi.
  • yoannyoann Membre
    23:59 modifié #14
    Plutôt étrange en effet

    Si tu veux/peut passe ton projet, comme ça je sèche
  • apocaalypsoapocaalypso Membre
    23:59 modifié #15
    Merci beaucoup Yoann !
    Je t'ai envoyé le lien par MP  ;)
  • schlumschlum Membre
    23:59 modifié #16
    Encore un débutant qui s'essaie au Mont-Blanc...  :o
    Vous voulez pas essayer de faire des choses simples ?  B)

    Alors évidemment, on utilise des classes toutes faites qui font papa/maman sans trop savoir comment ça fonctionne derrière... pratique. Mais gare au retour de bâton.
  • schlumschlum Membre
    23:59 modifié #17
    Celà  dit, texte et images, ça doit être le même code à  2 lignes près.
    - Transformation de NSImage en NSData / transformation de NSString en NSData
    - Transformation de NSData en NSImage / transformation de NSData en NSString
  • yoannyoann Membre
    23:59 modifié #18
    Le problème est réglé, ça venait d'une modif coté émetteur que je n'avais pas relevé dans le code de la page précédente (et qui n'avait pas lieux d'être) :

    [tt]- (void)connectionReceived:(NSNotification *)aNotification {
        NSFileHandle * incomingConnection = aNotification userInfo] objectForKey:[b]NSFileHandleNotificationFileHandleItem[/b;
        NSData * representationToSend = [[imageView image] TIFFRepresentation];
        [[aNotification object] acceptConnectionInBackgroundAndNotify];
        [incomingConnection writeData:representationToSend];
        [incomingConnection closeFile];
    }
    [/tt]


    [tt]- (void)connectionReceived:(NSNotification *)aNotification {
    NSString *message = [textField stringValue];
        NSFileHandle * incomingConnection = aNotification userInfo] objectForKey:[b]NSFileHandleNotificationDataItem[/b;
        NSData * representationToSend = [message dataUsingEncoding:NSASCIIStringEncoding];
        [[aNotification object] acceptConnectionInBackgroundAndNotify];
        [incomingConnection writeData:representationToSend];
        [incomingConnection closeFile];[/tt]
  • schlumschlum Membre
    23:59 modifié #19
    Oui, j'avais remarqué cette différence... c'est pour ça que je disais que ça devait être le même code  ;)
    Pourquoi NSFileHandleNotificationFileHandleItem d'un côté et NSFileHandleNotificationDataItem de l'autre... illogique.
  • apocaalypsoapocaalypso Membre
    23:59 modifié #20
    Encore merci Yoann !
  • apocaalypsoapocaalypso Membre
    23:59 modifié #21
    Je reposte une dernière fois pour savoir si cette fonctionnalité est réalisable en Bluetooth ?
    Il y aurait-il une classe qui s'occupe de ça ?
    Merci !
  • 23:59 modifié #22
    Faut toujours penser à  régarder dans les frameworks. Me semble qu'il y en a un pour la dent bleue
  • wiskywisky Membre
    23:59 modifié #23
    Mais c'est pas aussi évident que Bonjour :P
  • apocaalypsoapocaalypso Membre
    23:59 modifié #24
    Bonjour ? ça marche hors d'un réseau Wi-Fi ? Parce que je voudrais m'en détacher. 
  • wiskywisky Membre
    23:59 modifié #25
    Bonjour fonctionne pour les réseaux TCP/IP il me semble. BT n'est pas un réseau multi-point mais point-à -point !
    Regarde du côté des exemples BT fourni par Apple avec xCode ;)
  • AliGatorAliGator Membre, Modérateur
    23:59 modifié #26
    Oui Bonjour fonctionne sur iPhone, et over Bluetooth.
    C'est un peu bancal comme j'en ai déjà  fait l'expérience avec un projet client récent, genre l'interface réseau BT dans son profil PAN n'est pas détectée tant qu'elle n'est pas activée (qu'on a pas ouvert de socket dessus)... mais bon ça marchotte.

    En tout cas Bonjour (et le GameKit qui permet de faire communiquer 2 iPhones entre eux over BT et se base sur Bonjour pour ça) est supporté sur iPhone et passe over BT.
  • wiskywisky Membre
    23:59 modifié #27
    dans 1250868368:

    Oui Bonjour fonctionne sur iPhone, et over Bluetooth.
    C'est un peu bancal comme j'en ai déjà  fait l'expérience avec un projet client récent, genre l'interface réseau BT dans son profil PAN n'est pas détectée tant qu'elle n'est pas activée (qu'on a pas ouvert de socket dessus)... mais bon ça marchotte.

    En tout cas Bonjour (et le GameKit qui permet de faire communiquer 2 iPhones entre eux over BT et se base sur Bonjour pour ça) est supporté sur iPhone et passe over BT.


    J'ai failli dire une belle bêtise tout à  l'heure :P
  • AliGatorAliGator Membre, Modérateur
    23:59 modifié #28
    Eh bien en fait le BT est fortement utilisé pour du réseau point à  point, bien qu'il existe le concept de pico-réseau (jusqu'à  un truc comme 1 master et 8 slaves connectés en réseau, même si en réalité c'est du point à  point qui switche très rapidement d'un slave à  l'autre, mais bon, le protocole BT permet tout ça c'est prévu dans les specs).
    Bon, j'ai rarement vu dans les profils courants (AD2P, HFP, HSP, HID, OBEX, ...) des cas d'utilisation d'un pico-réseau mettant en relation plusieurs devices. En fait dans ces cas-là  BT est utilisé avec le protocole RFComm, autrement dit l'idée c'est d'avoir un protocole mimant une liaison série (vous savez, les câbles et interfaces RS-232)... mais sans fil.


    Par contre dans le profil PAN (Personal Area Network profile), cette utilisation multiclients c'est déjà  plus courant, pour la bonne et simple raison que ce profil a pour concept d'utiliser l'interface bluetooth comme une interface réseau, via le protocole BNEP (Bluetooth Network Encapsulation Protocol). Au final votre BT est vu comme une interface réseau au même titre qu'Ethernet ou Wifi, avec une IP et tout. Donc du coup l'aspect multipoint etc. a plus de sens.
Connectez-vous ou Inscrivez-vous pour répondre.