objets distribués... Je galère un peu

LeChatNoirLeChatNoir Membre, Modérateur
21:02 modifié dans API AppKit #1
Salut à  tous,
Je me remet un peu au code et j'ai besoin de faire dialoguer 2 instances de mon appli qui tourneraient sur 2 machines différentes.
J'ai lu un peu de littérature et il s'avère que les objets distribués semblent répondre à  mon besoin.
J'ai donc implémenté 2 méthodes dans mon objet : 1 pour activer le serveur (vended object) et 1 pour souscrire à  ce serveur.
Seulement voilà , le client a beau appelé une méthode du serveur, ça renvoit rien... Et à  force de trituré le code dans tous les sens, je perd un peu les pédales...

J'en appelle à  vos lumières...

Déclaration du serveur :
<br />-(void)activateDOServer {<br />	<br />	NSSocketPort *port = [[NSSocketPort alloc] initRemoteWithTCPPort:99 host:ourServiceName];<br />	NSConnection *theConnection = [NSConnection connectionWithReceivePort:port sendPort:nil];<br />	[theConnection setRootObject:distributedServer];<br />	NSString * serverName=[ABSYNCDOSERVERID stringByAppendingString:ourServiceName];<br />	[[NSSocketPortNameServer sharedInstance] registerPort:port name:serverName];<br />	<br />	NSLog(@&quot;Distributed Server %@ actif&quot;,serverName);<br />}<br /><br />


Et maintenant le client :
- (IBAction)subscribe:(id)sender<br />{<br />	// Get the vended server object<br />	NSString * distantService=[tableViewControler serviceNameAtIndex:[contactServiceList selectedRow]];<br />	NSLog(@&quot;Try to subscribe to %@&quot;,[ABSYNCDOSERVERID stringByAppendingString:distantService]);<br />	<br />	NSSocketPort *port = (NSSocketPort *)[[NSSocketPortNameServer sharedInstance] portForName:[ABSYNCDOSERVERID stringByAppendingString:distantService] host:distantService];<br />	NSConnection *theConnection = [NSConnection connectionWithReceivePort:nil sendPort:port];<br /><br />	id theProxy;<br />	theProxy = [[theConnection rootProxy] retain];<br />	NSLog(@&quot;test proxy : %@&quot;,[theProxy test]);<br />	<br />}<br />


Et bien sûr, [theProxy test] renvoie nil (alors que ça devrait renvoyer une chaine constante (juste pour test).

Pour résumer : j'ai 1 instance de mon appli qui tourne sur une machine. 1 seconde sur 1 autre machine. La 2nde tente de se connecter au serveur de la 1ere sans succès...

Si quelqu'un voit ce qui cloche...
Merci d'avance,
A+

Réponses

  • schlumschlum Membre
    21:02 modifié #2
    Attention, il faut être "root" pour écouter les ports <1024

    Ensuite, teste déjà  le serveur en essayant de te connecter avec "telnet"...
  • LeChatNoirLeChatNoir Membre, Modérateur
    21:02 modifié #3
    Salut,
    Merci du conseil. J'ai essayé avec 7999 mais pas mieux...
    Je n'arrive pas à  faire de telnet dessus non plus  :-\\

    J'ai donc remanié le code afin d'essayer plusieurs trucs et de simplifier. Voilà  où j'en suis.

    Le serveur :
    <br />-(void)activateDOServer {<br />	NSSocketPort *port = [[NSSocketPort alloc] init];<br />	NSConnection *connection = [NSConnection connectionWithReceivePort:port sendPort:nil];<br />	[connection setRootObject:distributedServer];<br />	NSString * serverName=ourServiceName;<br />	[[NSSocketPortNameServer sharedInstance] registerPort:port name:serverName];<br />}<br />
    


    Pour moi, ce code signifie :
    * définis une socket de communication,
    * raccroches y une NSConnection,
    * distributedServer sera l'objet derrière la NSConnection
    * publie la disponibilité de la socket dans le centre de distribution en tant que "servicedeToto" (par ex).

    bon là , j'essaye de faire un telnet sur "servicedeToto" mais ça me donne rien...

    Ensuite, côté client, je fais :
    <br />- (IBAction)subscribe:(id)sender<br />{<br />	// Get the vended server object<br />	NSString * distantServiceName=[tableViewControler serviceNameAtIndex:[contactServiceList selectedRow]];<br />	<br />	NSSocketPort *port = (NSSocketPort *)[[NSSocketPortNameServer sharedInstance] portForName:distantServiceName];<br />	NSConnection *theConnection = [NSConnection connectionWithReceivePort:nil sendPort:port];<br /><br />	id theProxy;<br />	theProxy = [[theConnection rootProxy] retain];<br />	NSLog(@&quot;test proxy : %@&quot;,[theProxy test]);<br />}<br />
    


    Ce que je traduis par :
    * récupères depuis le centre de distribution la socket qui a été publiée sous le  nom "servicedeToto"
    * rattaches y une NSConnection
    * récupère de cette NSConnection l'objet racine
    * ensuite, on devrait pouvoir lui envoyer un message tranquillou...


    Mais bon, il doit y avoir des choses que je zappe car quand je lance 2 instances de mon appli (1 sur un compte utilisateur, 1 sur un autre) et qu'à  partir d'1, j'essaye de souscrire à  l'autre, ça freeze...

    J'avais essayé en zappant le socket et en utilisant les shared NSConnection et ça a fonctionné. Mais ça ne fonctionne qu'en local. Mon but étant de dialoguer entre 2 machines, je dois passer par les socket.

    Si qqu'un a une idée... Merci !
  • schlumschlum Membre
    décembre 2007 modifié #4
    Je te conseille cet article :
    http://www.macdevcenter.com/pub/a/mac/2006/11/14/how-to-write-a-cocoa-web-server.html

    C'est pour un serveur Web, mais applicable à  ce que tu veux faire je pense (côté "server" tout du moins !)  ;)
  • LeChatNoirLeChatNoir Membre, Modérateur
    21:02 modifié #5
    Merci encore. Je suis aller y faire un tour et 1 phrase a retenue mon attention :
    It is important not to release socketPort before being finished with fileHandle.

    Je me demande si mon pb ne vient pas de là  : mes NSConnection sont en autorelease...

    Non ?
  • schlumschlum Membre
    21:02 modifié #6
    dans 1197462959:

    Merci encore. Je suis aller y faire un tour et 1 phrase a retenue mon attention :
    It is important not to release socketPort before being finished with fileHandle.

    Je me demande si mon pb ne vient pas de là  : mes NSConnection sont en autorelease...

    Non ?


    Attention aux "autorelease", ils sont relâchés au cycle suivant de la runLoop.
    C'est peut-être effectivement ton problème...
  • LeChatNoirLeChatNoir Membre, Modérateur
    21:02 modifié #7
    Cool, c'était bien ça !
    La NSConnection étant releasé, quand je tentais la connexion, ça moulinait, le serveur ne répondant pas mais le service étant toujours déclaré dans le Distributed Center.

    Donc solution : dans le activateDOServer :

    NSConnection *connection = [[NSConnection connectionWithReceivePort:port sendPort:nil] retain] ;

    Bon par contre, maintenant, j'ai un autre pb : mon code fonctionne sur 2 comptes utilisateurs locaux. Mais ça fontionne pas sur 2 machines distantes  :-\\

    J'vais regarder du côté de l'init de la socket....

    Merci de ton aide en tous cas !
    A+



  • psychoh13psychoh13 Mothership Developer Membre
    21:02 modifié #8
    dans 1197488355:
    Donc solution : dans le activateDOServer :

    NSConnection *connection = [[NSConnection connectionWithReceivePort:port sendPort:nil] retain] ;


    Ou alors tu utilisais la traditionnel technique d'alloc/init :
    NSConnection *connection = [[NSConnection alloc] initWithReceivePort:port sendPort:nil];
    :p
  • LeChatNoirLeChatNoir Membre, Modérateur
    21:02 modifié #9
    Salut,
    Il semble que je m'en sois sorti avec mes objets distribués.
    Je viens de me prendre la tête une belle poignée d'heure à  cause ... de la migration Intel !

    Eh oui, avec les diff ppc/intel, il faut faire gaffe au calcul du port de connexion ! Et comme j'ai un iMac G4 et un macbook, j'ai été directos confronté au pb.

    Bref, tout ça pour dire que pour faire dialoguer un Intel et un PPC via les objets distribués, il faut bien utiliser la fonction ntohs (network to Hosts) telle que :
    uint16_t port;
    port = ntohs(((struct sockaddr_in *)socketAddress)->sin_port);

    Et ensuite, tout fonctionne à  merveille !  <3 <br />Ouf !

    J'ai trouvé la réponse ici http://www.cocoadev.com/index.pl?DistributedObjectsAndIntelMachines

    A+
  • AliGatorAliGator Membre, Modérateur
    21:02 modifié #10
    En fait normalement il faut toujours utiliser cette fonction pour convertir les valeurs de ports dans l'endianness "network". Mais c'est vrai que tu peux ne pas t'en rendre compte si tu es sur une machine PPC où l'endianness est la même que celle utilisée par les normes réseau...

    Merci pour l'astuce, un rappel ne fait jamais de mal :P
  • schlumschlum Membre
    21:02 modifié #11
    Et de l'autre côté, il faut utiliser "htons"  ;)

    Il y a aussi "htonl" et "ntohl"

    These routines are most often used in conjunction with Internet addresses and ports as returned by gethostbyname(3) and getservent(3).
    


    Mais de toute manière il faut toujours faire super gaffe aux problèmes d'endian dès que quelque-chose sort de la machine (c'est valable pour l'écriture de fichiers aussi par exemple).
Connectez-vous ou Inscrivez-vous pour répondre.