Создание p2p-соединения iOS

Хорошо. Вот и уже неделю пытаюсь подключить устройства p2p с потоками. Все еще безрезультатно, и я схожу с ума и в отчаянии. Пожалуйста, не присылайте меня к руководству Рэя Вендерлиха и вики GCD или к руководству CFStream, поскольку я дошел до дыр.

Итак 1) Вариант Здесь я

  1. Получить Ip моего устройства
  2. Вручную введите ip в текстовое поле другого устройства
  3. Начать сетевое соединение на одном устройстве.
  4. Ошибка - подключение к хосту.

     + (NSString *)getIPAddress {
    
     NSString *address = @"error";
     struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;
    // retrieve the current interfaces - returns 0 on success
     success = getifaddrs(&interfaces);
     if (success == 0) {
     // Loop through linked list of interfaces
     temp_addr = interfaces;
      while(temp_addr != NULL) {
        if(temp_addr->ifa_addr->sa_family == AF_INET) {
        // Check if interface is en0 which is the wifi connection on the iPhone
           if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
                // Get NSString from C String
                address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
    
            }
    
        }
    
        temp_addr = temp_addr->ifa_next;
    }
     }
     // Free memory
    freeifaddrs(interfaces);
    return address;
    
    }
    
    • (void) initNetworkCommunication:(NSString*)ipToConnect { NSString *urlStr = ipToConnect; if (![urlStr isEqualToString:@""]) { NSURL *website = [NSURL URLWithString:urlStr]; if (!website) { NSLog(@"%@ is not a valid URL"); return; } CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)[website host], 80, &readStream, &writeStream);

    NSInputStream * inputStream = (__bridge_transfer NSInputStream *) readStream; NSOutputStream * outputStream = (__bridge_transfer NSOutputStream *) writeStream; [inputStream setDelegate: я]; [outputStream setDelegate: сам]; [inputStream scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode]; [outputStream scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode]; [inputStream open]; [outputStream open];

    }

    • (void) stream: (NSStream *) theStream handleEvent: (NSStreamEvent) streamEvent {

    NSLog (@ "событие потока% lu", streamEvent);

    switch (streamEvent) {

    case NSStreamEventOpenCompleted:
        NSLog(@"Stream opened");
        break;
    case NSStreamEventHasBytesAvailable:
    
        if (theStream == inputStream) {
    
            uint8_t buffer[1024];
            int len;
    
            while ([inputStream hasBytesAvailable]) {
                len = [inputStream read:buffer maxLength:sizeof(buffer)];
                if (len > 0) {
    
                    NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
    
                    if (nil != output) {
    
                        NSLog(@"server said: %@", output);
                        //[self messageReceived:output];
    
                    }
                }
            }
        }
        break;
    
    
    case NSStreamEventErrorOccurred:
    
        NSLog(@"Can not connect to the host!");
        break;
    
    case NSStreamEventEndEncountered:
    
        [theStream close];
        [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
     //   [theStream release];
        theStream = nil;
    
        break;
    default:
        NSLog(@"Unknown event");
    

    }

    }

Вариант 2 с НОД. 1. То же 2. Настройте оба устройства на прослушивание ввода.

+(void)listenSocket:(GCDAsyncSocket*)listenSocket
{

listenSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

NSError *error = nil;
if (![listenSocket acceptOnPort:80 error:&error])
{
    NSLog(@"I goofed: %@", error);
}

}

3) Пытался подключиться с ручным вводом IP

 +(void)connectToDeviceWithIp:(NSString*)deviceIp andSend:(HSUserCard*)tempCard andSocket:(GCDAsyncSocket*)tempSocket
{

tempSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *err = nil;
if (![tempSocket connectToHost:deviceIp onPort:80 error:&err])
    NSLog(@"I goofed: %@", err);



[tempSocket writeData:[NSKeyedArchiver archivedDataWithRootObject:tempCard] withTimeout:-1 tag:1];
}

4) Ничего не дало результата - я сделал несколько перерывов для каждой функции-делегата = НИЧЕГО.

Омг - я решил эту задачу на Android за 20 минут! Но здесь это просто сводит с ума. Пробовал в нескольких сетях. Через 3G, домашний wifi. Пожалуйста, помогите кому-нибудь!


person Morckovka    schedule 22.12.2014    source источник
comment
Могу я отправить вам руководство по форматированию?   -  person Blindy    schedule 22.12.2014
comment
Во всех случаях ваша проблема заключается в том, что вы сохраняете свои сокеты как локальные переменные внутри метода, поэтому, как только метод выходит, сокеты перестают существовать. Вам нужно сохранить их как свойства в ваших классах.   -  person Paulw11    schedule 22.12.2014
comment
Не тот случай. Как я пробовал и то, и другое. Вроде как переменные и как свойства. Это было взято из примера Рэя Вендерлиха. А во втором случае, если вы внимательно посмотрите, это свойства, и я их сохраняю. Найдите self.tempSocket   -  person Morckovka    schedule 22.12.2014
comment
@ Paulw11 во втором случае я передаю там свойства методу   -  person Morckovka    schedule 22.12.2014
comment
Вы передаете сокет, но сразу же переназначаете новый сокет этой переменной - даже если это параметр, это все еще локальная переменная, поэтому она будет выпущена, как только метод класса завершится. Я не вижу «себя». в любом месте   -  person Paulw11    schedule 22.12.2014
comment
Я создал образец проекта с использованием GCDAsyncSocket - github.com/paulw11/SocketDemo/tree/master   -  person Paulw11    schedule 22.12.2014
comment
@ Paulw11 хорошо - спасибо! Я попытаюсь.   -  person Morckovka    schedule 22.12.2014
comment
@ Paulw11 Да, интегрировано ~! Работает!!! Спасибо чувак!!!   -  person Morckovka    schedule 22.12.2014


Ответы (1)


Проблема, которую я вижу во всех ваших различных попытках, заключается в том, что вы сохраняете сокет в локальной переменной - это означает, что после выхода из метода он будет выпущен, и с этим сокетом будет невозможно обмен данными.

Вам необходимо сохранить ссылки на сокеты в strong свойствах.

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

Он доступен здесь, https://github.com/paulw11/SocketDemo.

person Paulw11    schedule 23.12.2014