структуры передачи по UDP слабо типизированы - PullRequest
0 голосов
/ 19 ноября 2009

Я новичок в сетевом программировании и в основном учусь на практике. Я использую программу Майка Эша "Sphere Net" из iPhone Cool Projects . Я понимаю, что происходит в программе, но я готов начать расширять ее, и я ожидаю посылать разумное разнообразие типов пакетов (каждый представлен в виде структуры). Кажется, не сложно объявлять разные методы для каждого типа пакета.

Если бы я имел дело с классами target-c, я бы попросил функции взять суперкласс в качестве параметра или использовать id. Но поскольку я использую структуры по стоимости, я не думаю, что смогу использовать эту стратегию.

Я прошу указатели на хороший справочник, объясняющий, как типичная программа может обрабатывать возможное множество типов пакетов (структур), будь то ответ с переполнением книги, ссылки или стека.

(перевод: я не хочу писать несколько совершенно новых методов, которые почти одинаковы, за исключением типа пакета, с которым они имеют дело каждый раз, когда я решаю добавить пакет нового типа)

Для справки, основная схема программы типа Sphere Net находится в заголовке:

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'; 

в реализации:

-(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]; 
} 

1 Ответ

0 голосов
/ 23 ноября 2009

После некоторого исследования руки я нашел решение. Это в основном так:

создание определенных пакетов с определенной информацией создать пакет «передачи», структура которого выглядит следующим образом:

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

затем вы используете memcopy(const void*, const void*, size); для копирования данных конкретных структур в массиве символов структуры transimssion.

Затем на приемном конце вы знаете, что первым байтом того, что вы получите, будет идентификатор типа, поэтому прочитайте первые четыре байта, и оттуда вы сможете решить, что делать с остальными байтами .

Примером этого является: проблема с iphone при получении пакетов UDP

...