2013-07-12 4 views
11

ठीक है, इसमें this part of a multiplayer tutorial से बहुत सारे नेटवर्क कोडिंग शामिल हैं।GKSession के साथ समस्याएं और SendDataToAllPeers: withDataMode: त्रुटि:

मूल रूप से, मैं उपरोक्त लिंक किए गए ट्यूटोरियल के अनुसार गेमकिट का उपयोग करके एक मल्टीप्लेयर गेम को कार्यान्वित करने की कोशिश कर रहा हूं। मैंने सभी आवश्यक नेटवर्क कोडिंग में डाल दिया है और इसे कम या ज्यादा समझ में आया है, हालांकि मैंने विधि कॉल की लाइन के साथ कहीं भी एक झटका लगाया है। असल में, मेरे पास जो सेटअप है वह यह है कि एक डिवाइस होस्ट के रूप में कार्य करता है और शेष क्लाइंट के रूप में कार्य करता है। मेरे पास मेजबान और क्लाइंट्स के क्रमशः दो अलग-अलग UIViewcontroller एस हैं जहां कनेक्शन स्थापित किया गया है।

अब बात यह है कि कनेक्शन स्थापित हो जाता है, लेकिन यह केवल होस्ट है जो कनेक्शन को पहचानता है, ग्राहक नहीं। समस्या यहाँ है:

- (void)sendPacketToAllClients:(Packet *)packet 
{ 
    [_players enumerateKeysAndObjectsUsingBlock:^(id key, Player *obj, BOOL *stop) 
    { 
     obj.receivedResponse = [_session.peerID isEqualToString:obj.peerID]; 
    }]; 

    GKSendDataMode dataMode = GKSendDataReliable; 
    NSData *data = [packet data]; 
    NSError *error; 
    if (![_session sendDataToAllPeers:data withDataMode:dataMode error:&error]) 
    { 
     NSLog(@"Error sending data to clients: %@", error); 
    } 
} 

यह GameMultiplayer, जहां वास्तविक खेल से लागू किया जाएगा में किया जाता है। यह तरीका क्या करना है, यह सुनिश्चित करने के लिए कि प्रत्येक होस्ट को कनेक्शन अनुरोध प्राप्त हुआ है और उनके साथ कनेक्ट करने में सक्षम है, प्रत्येक क्लाइंट को डेटा पैकेट भेज रहा है। बाद [_session sendDataToAllPeers:data withDataMode:dataMode error:&error] (if बयान में विधि) कहा जाता है, इस पद्धति शुरू किया जा माना जाता है:

- (void)receiveData:(NSData *)data fromPeer:(NSString *)peerID inSession:(GKSession *)session context:(void *)context 
{ 
#ifdef DEBUG 
    NSLog(@"Game: receive data from peer: %@, data: %@, length: %d", peerID, data, [data length]); 
#endif 

    Packet *packet = [Packet packetWithData:data]; 
    if (packet == nil) 
    { 


     NSLog(@"Invalid packet: %@", data); 
     return; 
    } 

    Player *player = [self playerWithPeerID:peerID]; 
    if (player != nil) 
    { 
     player.receivedResponse = YES; // this is the new bit 
    } 

    if (self.isServer) 
     [self serverReceivedPacket:packet fromPlayer:player]; 
    else 
     [self clientReceivedPacket:packet]; 
} 

इस विधि ट्यूटोरियल मैं ऊपर लिंक (जो here) के अगले भाग में है और माना जाता है मेजबान जो क्लाइंट सभी क्लाइंट को भेजता है और इस नेटवर्किंग श्रृंखला में अगली विधियों को लागू करता है। हालांकि, विधि कभी नहीं बुलाया जाता है। कोई डीबग ब्रेकपॉइंट ट्रिगर नहीं होता है और मुझे कंसोल में कुछ भी नहीं मिलता है।

मैं समझता हूं कि मुझे अधिक स्रोत सामग्री प्रदान करने की आवश्यकता है, लेकिन नेटवर्क कोडिंग पहले से ही लागू हो चुकी है, इसलिए मैं इसे नीचे रखना चाहता हूं कि लोगों को क्या देखना है। इसके अलावा, [_session setDataReceiveHandler:self withContext:nil] और _session.delegate = self किसी अन्य विधि में लिखे गए हैं जिन्हें GameMultiplayer में कहा जाता है, इसलिए यह समस्या नहीं है। क्या किसी को पता है कि मुझे क्या ठीक करने की ज़रूरत है?

संपादित करें: के रूप में अनुरोध किया है, यहाँ जहां GKSession आरंभ नहीं हो जाता है:

@property (nonatomic, strong, readonly) GKSession *session; //This is done in the header file 

@synthesize session = _session; //This is done in the main file 

- (void)startAcceptingConnectionsForSessionID:(NSString *)sessionID 
{ 

    if (_serverState == ServerStateIdle) 
    { 
     _serverState = ServerStateAcceptingConnections; 

     _connectedClients = [NSMutableArray arrayWithCapacity:self.maxClients]; 

     _session = [[GKSession alloc] initWithSessionID:sessionID displayName:nil sessionMode:GKSessionModeServer]; 
     _session.delegate = self; 
     _session.available = YES; 
    } 
} 

सत्र MatchmakingServer में आरंभ नहीं हो जाता है, जो मेजबान दृश्य नियंत्रक में प्रयोग किया जाता है। सत्र तब ऐप के मुख्य दृश्य नियंत्रक को पास किया जाता है, जो तब GameMultiplayer प्रारंभ करता है और उसे GKSession भेजता है।

- (IBAction)startAction:(id)sender 
{ 
    if (_matchmakingServer != nil && [_matchmakingServer connectedClientCount] > 0) 
    { 
     NSString *name = [self.nameTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
     if ([name length] == 0) 
       name = _matchmakingServer.session.displayName; 

     [_matchmakingServer stopAcceptingConnections]; 

     [self.delegate hostViewController:self startGameWithSession:_matchmakingServer.session playerName:name clients:_matchmakingServer.connectedClients]; 
    } 
} 

और फिर मुख्य दृश्य नियंत्रक यहाँ संभालती है कि विधि कॉल:: यहाँ जहां मेजबान दृश्य नियंत्रक मुख्य दृश्य नियंत्रक को भेज देता है है

- (void)hostViewController:(MatchmakerHost *)controller startGameWithSession:(GKSession *)session playerName:(NSString *)name clients:(NSArray *)clients 
{ 

    [self dismissViewControllerAnimated:NO completion:^ 
    { 

     [self startGameWithBlock:^(GameMultiplayer *aGame) 
      { 
       [aGame startServerGameWithSession:session playerName:name clients:clients]; 
      }]; 
    }]; 
} 

और अंत में, यह वह जगह है जहाँ कि विधि कॉल है GameMultiplayer में लागू:

- (void)startServerGameWithSession:(GKSession *)session playerName:(NSString *)name clients:(NSArray *)clients 
{ 
    _clients = clients; 

    const char* className = class_getName([[_clients objectAtIndex:0] class]); 
    NSLog(@"yourObject is a: %s", className); 

    self.isServer = YES; 

    _session = session; 
    _session.available = NO; 
    _session.delegate = self; 
    [_session setDataReceiveHandler:self withContext:nil]; 

    _state = GameStateWaitingForSignIn; 

    [self.delegate gameWaitingForClientsReady:self]; 

    // Create the Player object for the server. 
    Player *player = [[Player alloc] init]; 
    player.name = name; 
    player.peerID = _session.peerID; 
    player.position = PlayerPositionBottom; 
    [_players setObject:player forKey:player.peerID]; 

    // Add a Player object for each client. 
    int index = 0; 
    for (NSString *peerID in clients) 
    { 
     Player *player = [[Player alloc] init]; 
     player.peerID = peerID; 
     [_players setObject:player forKey:player.peerID]; 

     if (index == 0) 
      player.position = ([clients count] == 1) ? PlayerPositionTop : PlayerPositionLeft; 
     else if (index == 1) 
      player.position = PlayerPositionTop; 
     else 
      player.position = PlayerPositionRight; 

     index++; 
    } 

    NSLog(@"Players:"); 

    Packet *packet = [Packet packetWithType:PacketTypeSignInRequest]; 
    [self sendPacketToAllClients:packet]; 

// for (int i = 0; i < [_players count]; i++) { 
//  NSLog([NSString stringWithFormat:@"%@", [clients objectAtIndex:i]]); 
// } 
} 
+0

आपने GKSession ऑब्जेक्ट को कैसे सेट किया? GKSession * gk_session = [[GKSession alloc] initWithSessionID: nil displayName: nil sessionMode: GKSessionModePeer]; – ldindu

+0

संपादित किया गया है – RaysonK

+0

[_session setDataReceiveHandler: self withContext: nil]; आप यहां स्वयं को पारित कर रहे हैं, हैंडलर वह ऑब्जेक्ट है जिसे आप कॉल करना चाहते हैं जब इसे अन्य सहकर्मियों से डेटा प्राप्त होता है। और हैंडलर को निम्नलिखित हस्ताक्षर के साथ एक विधि लागू करनी होगी: - (शून्य) प्राप्त डेटा: (एनएसडीएटी *) डेटा से पीयर: (एनएसएसटींग *) सहकर्मी सत्र: (जीकेएसशन *) सत्र संदर्भ: (शून्य *) संदर्भ; मैं सोच रहा हूं, क्या आप सही हैंडलर पास कर रहे हैं या नहीं? – ldindu

उत्तर

0

मुझे लगता है कि आप तेजी से भेज रहे हैं। जब सर्वर कनेक्शन के बारे में महसूस करता है तो यह वास्तव में कनेक्शन स्थापित करने के लिए ग्राहक को पुष्टि भेज देगा - इसलिए ग्राहक इसके बारे में जानता है।

यदि आप इससे पहले पैकेट भेज रहे हैं - यह खो जाएगा।

बस इस कार्य करें:

[self performSelector:@selector(sendPacketToAllClients) withObject:nil afterDelay:1.0]; 

के बजाय:

[self sendPacketToAllClients]; 

मुझे लगता है कि कनेक्शन क्लाइंट पर छोटे देरी से अलग पल में स्थापित है एक ही समस्या थी। सबसे अच्छा क्लाइंट से पहला पैकेट भेजना है कि वह सर्वर से पैकेट प्राप्त करने के लिए तैयार है - और वहां से सामान्य रूप से आगे बढ़ने के बजाय।

इसके अलावा डिबगिंग का प्रयास करें:

- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state 

दोनों उपकरणों (सर्वर और ग्राहक) पर।

0

मुझे GKSession के साथ भी मेरी परेशानी हुई है। मुझे आज (इस साइट पर) सीखने में दिलचस्पी थी कि मल्टीपायर कनेक्टिविटी फ्रेमवर्क का उपयोग करने के पक्ष में जीकेएसशन को बहिष्कृत किया जा रहा है। भाग्य के साथ, वेंडरलिच एट अल। नई तकनीक का उपयोग कर एक ट्यूटोरियल करेगा। :)

सिस्टम में जीकेएसशन के लिए कुछ समानताएं हैं, इसलिए अपने सिर को चारों ओर लपेटना बहुत मुश्किल नहीं है।

Apple's doc link

संबंधित मुद्दे