2009-11-18 6 views
0

Je suis novice en programmation de réseau et je suis fondamentalement en train d'apprendre. Je suis en train de suivre le programme Mike Ashes "Sphere Net" de iPhone Cool Projects. Je comprends ce qui se passe dans le programme, mais je suis prêt à commencer à l'étendre et je m'attends à envoyer une variété raisonnable de types de paquets (chacun étant représenté par une structure). Il ne semble pas utile de déclarer des méthodes différentes pour chaque type de paquet.Passer des structures sur UDP faiblement dactylographiées

Si j'avais affaire à des classes d'objectifs-c, j'aurais les fonctions prendre la super classe comme paramètre, ou utiliser id. Mais puisque j'utilise des structures de valeur-value, je ne pense pas pouvoir utiliser cette stratégie. Je demande des pointeurs vers une bonne référence expliquant comment un programme typique peut gérer une grande variété possible de types de paquets (struct), qu'il s'agisse d'un livre, d'un lien ou d'une réponse de dépassement de pile.

(traduction: Je ne veux pas écrire plusieurs méthodes entièrement nouvelles, qui sont presque les mêmes, sauf pour le type de paquet qu'ils traitent chaque fois que je décide d'ajouter un nouveau type de paquet)

Pour référence les grandes lignes d'un programme de type net Sphere est dans l'en-tête:

typedef struct { 
    uint32_t identifier; 
    uint32_t datatype; 
} PacketHeader; 

typedef struct { 
    PacketHeader header; 
    int32_t dataItem1; 
    int32_t dataItem2; 
} MyPacket; 
static const uint32_t kPacketIdentifier = 'pkt'; 

dans la mise en œuvre:

-(void) init{ 
// do all the setup, open the sockets, start bonjour. 
     // start the listener thread 
     [NSThread detachNewThreadSelector:@selector(listenThread) toTarget:self withObject:nil]; 
} 

- (void)objectOfInterestChanged:(ObjectOfInterest *)interestingObject { 

    PositionPacket packet; 

    packet.dataItem1 = CFSwapInt32HostToBig(round(interestingObject.someFloat)); 
    packet.dataItem2 = CFSwapInt32HostToBig(round(interestingObject.someFloat)); 

    [self sendUpdatePacket:packet]; 
} 

- (void)sendUpdatePacket:(MyPacket)packet{ 

    packet.header.identifier = CFSwapInt32HostToBig(kPacketIdentifier); 
    packet.header.datatype = CFSwapInt32HostToBig(kPacketType); 

    for(NSNetService *service in _services) 
     for(NSData *address in [service addresses]) 
      sendto(_socket, &packet, sizeof(packet), 0, [address bytes], [address length]); 
} 

- (void)listenThread { 
    while(1) 
    { 
     MyPacket packet; 
     struct sockaddr addr; 
     socklen_t socklen = sizeof(addr); 
     ssize_t len = recvfrom(_socket, &packet, sizeof(packet), 0, &addr, &socklen); 
     if(len != sizeof(packet)) 
      continue; 
     if(CFSwapInt32BigToHost(packet.basePacket.header.identifier) != kPacketIdentifier) 
      continue; 
     //if(CFSwapInt32BigToHost(packet.basePacket.header.datatype) != kPacketType) 
     // continue; 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
     NSData *packetData = [NSData dataWithBytes:&packet length:sizeof(packet)]; 
     NSData *addressData = [NSData dataWithBytes:&addr length:socklen]; 
     NSArray *arguments = [NSArray arrayWithObjects:packetData, addressData, nil]; 
     //SEL mainThreadSEL = @selector(mainThreadReceivedPositionPacket:); 
     SEL mainThreadSEL; 
     if(CFSwapInt32BigToHost(packet.basePacket.header.datatype) == kPacketType) 
      mainThreadSEL = @selector(mainThreadReceivedPacket:); 
     [self performSelectorOnMainThread:mainThreadSEL withObject:arguments waitUntilDone:YES]; 
     [pool release]; 
    } 
} 

- (void)mainThreadReceivedPacket:(NSArray *)arguments { 
    // extract the objects from the array created above 
    NSData *packetData = [arguments objectAtIndex:0]; 
    NSData *addressData = [arguments objectAtIndex:1]; 
    const MyPacket *packet = [packetData bytes]; 

    // ...accounting for differences in endianness 
    int32_t x = CFSwapInt32BigToHost(packet->dataItem1); 
    int32_t y = CFSwapInt32BigToHost(packet->dataItem2); 

    AnObject *update; 
    update.interestingUpdate = CGThingMake(x, y); 

    [delegate networkController:self didReceiveUpdate:update fromAddress:addressData]; 
} 

Répondre

0

Après quelques recherches un holding main Je suis arrivé une solution. Il est fondamentalement comme ceci:

créer des paquets spécifiques avec des informations spécifiques créer un paquet « de transmission » qui est un struct fait comme:

typedef struct TransmissionStruct{ 
    size_t typeOfPacketIdentifier; 
    char arrayOfBytesHoldingSpecificStruct [<sizeoflargeststruct>] 
} Transmission Struct 

vous utilisez ensuite memcopy(const void*, const void*, size); pour copier les données des struct spécifiques dans le charbon tableau de la structure transimssion. Puis, du côté de la réception, vous savez que le premier octet de tout ce que vous recevrez sera l'identificateur de type, alors lisez les quatre premiers octets, et à partir de là, vous pouvez décider quoi faire avec le reste de la octets.

Un exemple de ceci est à: iphone problem receiving UDP packets

Questions connexes