Bonne réception des packets

TomDevTomDev Membre
mai 2009 modifié dans API AppKit #1
Bonjour,

J'utilise actuellement SmallSocket pour utiliser les sockets mais je rencontre un problème lorsque le serveur m'envoie plusieurs messages  très rapidement mon programme va recevoir que 2 messages sur 3 par exemple mais il lis le premier saute le second et lis le dernier. J'utilise une boucle qui détecte dés qu'il à  reçu au moins 1 caractère il stop puis passe à  la seconde boucle ect...
J'en est déduis que le problème est plutôt temporelle (le serveur envoie les trois messages avec une intervalle trop courte).

Mais je ne trouve pas de solution.

Merci d'avance pour votre aide.    ;)

Edit :
Voici un exemple de code après avoir créer mon socket :
[socketT connectToHostName:@&quot;XXX.XXX.XXX.XXX&quot; port:XXX];<br />&nbsp; &nbsp; NSMutableData *reponse = [NSMutableData data];<br />&nbsp; &nbsp; while ([socketT readData:reponse] &lt;= 0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; NSString *receiveData = [[NSString alloc] initWithData:reponse encoding:NSUTF8StringEncoding];<br />&nbsp; &nbsp; NSLog(@&quot;Reçu : %@&quot;,receiveData);
Comme sa j'arrive à  recevoir un message mais si jamais je devais en recevoir plusieurs là  je plante j'ai essayer comme sa :
[socketT connectToHostName:@&quot;XXX.XXX.XXX.XXX&quot; port:XXX];<br />&nbsp; &nbsp; NSMutableData *reponse = [NSMutableData data];<br />&nbsp; &nbsp; while ([socketT readData:reponse] &lt;= 0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; NSString *receiveData = [[NSString alloc] initWithData:reponse encoding:NSUTF8StringEncoding];<br />&nbsp; &nbsp; NSLog(@&quot;Reçu : %@&quot;,receiveData);<br /> NSMutableData *reponse2 = [NSMutableData data];<br />&nbsp; &nbsp;  while ([socketT readData:reponse2] &lt;= 0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp;  }<br />&nbsp; &nbsp;  NSString *receiveData2 = [[NSString alloc] initWithData:reponse2 encoding:NSUTF8StringEncoding];<br />&nbsp; &nbsp;  NSLog(@&quot;Reçu : %@&quot;,receiveData);
Mais cela ne me permet pas de recevoir le second message pourtant si j'utilise un sniffeur de packet j'ai bien reçu 2 messages mais mon programme ne l'a pas detecter.
(Je précise que mon code est un exemple donc pas de gestion de mémoire et mes boucle dans ces exemple sont infinis mais j'ai une gestion d'erreurs au cas où il n'y a pas de connexion ou que trop de temps c'est passer pour recevoir le message).

Réponses

  • NoNo Membre
    02:34 modifié #2
    Que vaut SmallSocket ?
    Car je pense que le problème vient de cette classe.

    As tu essayé d'utiliser les sockets via NSStream ?
    C'est natif cocoa, donc cela est peut-être plus robuste.
  • TomDevTomDev Membre
    02:34 modifié #3
    J'aimerais utiliser NSStream mais il y a peu d'informations pour l'utiliser correctement mais bon je pense que je vais être obliger de passer un weekend à  apprendre à  l'utiliser.

    Merci de ta réponse.
  • AliGatorAliGator Membre, Modérateur
    02:34 modifié #4
    Comment ça peu d'informations ? La doc Apple de NSStream et surtout le "Companion Guide" qu'ils mentionnent dans cette doc, à  savoir le Stream Programming Guide for Cocoa qui détaille tout ne te suffit pas ??! La doc est pourtant bavarde là  dessus, que te donne de plus SmallSocket de ce côté ?
  • NoNo Membre
    02:34 modifié #5
    Sinon, un exemple classique d'utilisation d'un socket en lecture :
    <br />{<br />&nbsp;  NSInputStream *instream;<br /><br />&nbsp;  // création du socket en lecture pour le serveur à  l&#39;adresse XXX.XXX.XXX.XXX et port XXXXX<br />&nbsp;  [NSStream getStreamsToHost:[NSHost hostWithAddress:@&quot;XXX.XXX.XXX.XXX&quot;] port:XXXXX inputStream:&amp;instream outputStream:NULL];<br /><br />&nbsp;  // ouverture du socket<br />&nbsp;  [instream open];<br /><br />&nbsp;  // attente s&#39;il y a des données reçues<br />&nbsp;  if ([instream hasBytesAvailable])<br />&nbsp;  {<br />&nbsp; &nbsp; &nbsp; uint8_t buffer[200];<br /><br />&nbsp; &nbsp; &nbsp; // données reçues : on les lit<br />	&nbsp; &nbsp; int nb=[instream read:buffer maxLength:sizeof(buffer)];<br />	&nbsp; &nbsp; if (nb&gt;0)<br />			{<br />			&nbsp;  // création d&#39;une chaine à  partir des données reçues<br />			&nbsp;  NSString *reponse=[[NSString alloc] initWithBytes:buffer length:nb encoding:NSUTF8StringEncoding];<br />			&nbsp;  NSLog(@&quot;reponse=%@&quot;, reponse);<br />			&nbsp;  [reponse release];<br />			}<br />	 }<br /><br />&nbsp;  // fermeture du port<br />&nbsp;  [instream close];<br />}<br />
    


    En lisant le companion-guide donné en lien par Ali, tu y verras comment utilisant les sockets de manière asynchrone (via un delegate). Ainsi, il n'y aura que peu de chance de perdre des données.
  • dilarogadilaroga Membre
    02:34 modifié #6
    Que vaut SmallSocket ?

    hmm... Ce projet ne semble plus maintenu, la dernière version publique en 0.6 date de 2001. Pour l'histoire, NSStream a vu le jour avec Mac OS 10.3 publié en 2003.
  • TomDevTomDev Membre
    02:34 modifié #7
    Merci beaucoup pour vos réponses je me penche sur NSStream 

    (Merci pour l'exemple).
  • GreensourceGreensource Membre
    02:34 modifié #8
    Je me permet d'insérer ma demande dans ce fil puisque je penses qu'elle y correspond bien.
    Moi j'aurais besoin d'envoyer un paquet, non pas à  une adresse IP mais directement à  une adresse MAC. Et pour ça j'ai besoin de construire l'entête Ethernet moi même à  la main.
    Or je n'ai pas l'impression que NSStream puisse me permettre ça?

  • AliGatorAliGator Membre, Modérateur
    02:34 modifié #9
    Non, en effet c'est du très bas niveau ce que tu comptes faire, sur la couche "data link layer" (ou à  la limite "network layer" ?) du modèle OSI, NSStream fonctionne au niveau des couches supérieures, et non si bas niveau.

    Tu ne peux pas faire une requête RARP pour obtenir l'adresse IP de la machine à  partir de son adresse MAC ? C'est un peu bas niveau aussi, mais au moins une fois que tu as l'adresse IP tu te retrouves dans un use case classique et tu peux utiliser les classes et les fonctions réseau classiques...
  • GreensourceGreensource Membre
    02:34 modifié #10
    C'est justement ce que je dois faire.
    Une requête RARP sur une sorte d'adresse MAC "broadcast" et je dois enregistrer l'IP de la première réponse.

    Donc pour la requête RARP je pensais passer par NSStream ou bien CFSocket mais je ne m'y connais que très peu et c'est franchement pas évident. Je cherche des tutos qui pourrais me donner des exemples mais dur dur de trouver quelque chose qui fonctionne.
  • zoczoc Membre
    02:34 modifié #11
    dans 1243945411:
    Or je n'ai pas l'impression que NSStream puisse me permettre ça?


    Clairement pas. NSStream propose un niveau d'abstraction bien trop élevé, et fonctionne, dans le cas des communications réseau, exclusivement en TCP, qui n'est pas le bon protocole pour faire des requêtes RARP...

    La seule solution que je vois, c'est l'ouverture de sockets en mode "RAW", ce qui permet de définir soi même le contenu complet d'un paquet, y compris l'entête. Et faire cela, la solution la plus simple est de consulter le code source d'un outil sachant faire du rarp (il en existe sans doute en opensource).
  • thierryHthierryH Membre
    02:34 modifié #12
    si ca peut t'aider mais c'est de la programmation de bas niveau
    http://www.wireshark.org/
    il y a la version mac et le code source
    A+
  • GreensourceGreensource Membre
    02:34 modifié #13
    En effet ^^ Je l'utilise justement, je n'avais pas pensé à  regarder le code source ;)
    Merci
Connectez-vous ou Inscrivez-vous pour répondre.