2017-12-01 6 views
0

나는이 코드를 사용하여 XMPP에 연결할 수있는 ipv6 네트워크 연결을 허용했습니다.ipv4 네트워크에서 XMPP 연결 문제

asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:xmppQueue]; 
[asyncSocket setPreferIPv4OverIPv6:NO]; 

- (void)setPreferIPv4OverIPv6:(BOOL)flag 
{ 
    // Note: YES means kPreferIPv6 is OFF 

    dispatch_block_t block = ^{ 

     if (flag) 
      config &= ~kPreferIPv6; 
     else 
      config |= kPreferIPv6; 
    }; 

    if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey)) 
     block(); 
    else 
     dispatch_async(socketQueue, block); 
} 

- (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr 
{ 
    LogTrace(); 

    NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); 

    LogVerbose(@"IPv4: %@:%hu", [[self class] hostFromAddress:address4], [[self class] portFromAddress:address4]); 
    LogVerbose(@"IPv6: %@:%hu", [[self class] hostFromAddress:address6], [[self class] portFromAddress:address6]); 

    // Determine socket type 

    BOOL preferIPv6 = (config & kPreferIPv6) ? YES : NO; 

    BOOL useIPv6 = ((preferIPv6 && address6) || (address4 == nil)); 

    // Create the socket 

    __block int socketFD; 
    __block NSData *address; 
    __block NSData *connectInterface; 

    if (useIPv6) 
    { 
     LogVerbose(@"Creating IPv6 socket"); 

     socket6FD = socket(AF_INET6, SOCK_STREAM, 0); 

     socketFD = socket6FD; 
     address = address6; 
     connectInterface = connectInterface6; 
    } 
    else 
    { 
     LogVerbose(@"Creating IPv4 socket"); 

     socket4FD = socket(AF_INET, SOCK_STREAM, 0); 

     socketFD = socket4FD; 
     address = address4; 
     connectInterface = connectInterface4; 
    } 

    if (socketFD == SOCKET_NULL) 
    { 
     if (errPtr) 
      *errPtr = [self errnoErrorWithReason:@"Error in socket() function"]; 

     return NO; 
    } 

    // Bind the socket to the desired interface (if needed) 

    if (connectInterface) 
    { 
     LogVerbose(@"Binding socket..."); 

     if ([[self class] portFromAddress:connectInterface] > 0) 
     { 
      // Since we're going to be binding to a specific port, 
      // we should turn on reuseaddr to allow us to override sockets in time_wait. 

      int reuseOn = 1; 
      setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn)); 
     } 

     const struct sockaddr *interfaceAddr = (const struct sockaddr *)[connectInterface bytes]; 

     int result = bind(socketFD, interfaceAddr, (socklen_t)[connectInterface length]); 
     if (result != 0) 
     { 
      if (errPtr) 
       *errPtr = [self errnoErrorWithReason:@"Error in bind() function"]; 

      return NO; 
     } 
    } 

    // Prevent SIGPIPE signals 

    int nosigpipe = 1; 
    setsockopt(socketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe)); 

    // Start the connection process in a background queue 

    int aConnectIndex = connectIndex; 

// dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
// dispatch_async(globalConcurrentQueue, ^{ 

     int result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]); 
     if (result != 0) { 

      socket6FD = SOCKET_NULL; 
      socket4FD = socket(AF_INET, SOCK_STREAM, 0); 

      socketFD = socket4FD; 
      address = address4; 
      connectInterface = connectInterface4; 

      result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]); 
     } 
    //}); 

    LogVerbose(@"Connecting..."); 

    return YES; 
} 

위의 방법은 항상 두 네트워크에서 ipv6을 연결합니다.

[asyncSocket setPreferIPv4OverIPv6 : NO]를 커밋하려면; ipv4.please가 나랑 두 네트워크를 연결할 수 있도록 연결되지 않는보다 내가이 코드를 사용 ipv6.if IPv4 네트워크 만의 적절한 일 이상이 코드는

+0

이 줄을 쓰는 곳은'asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate : self delegateQueue : xmppQueue];'이다. 클래스 또는 파일을 의미합니까? –

+0

XMPPStream.m 파일의 @NiravKotecha – iOS

+0

실제로'setPreferIPv4OverIPv6' 메서드를 호출하고 성공적으로 실행하지 않습니다. 우리가 ipv6을 가지고 있지 않기 때문에'asyncSocket.IPv4PreferredOverIPv6 = NO'를 추가 한 후에 –

답변

0

connectWithAddress4...

- (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr 
{ 
    LogTrace(); 

    NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue"); 

    LogVerbose(@"IPv4: %@:%hu", [[self class] hostFromAddress:address4], [[self class] portFromAddress:address4]); 
    LogVerbose(@"IPv6: %@:%hu", [[self class] hostFromAddress:address6], [[self class] portFromAddress:address6]); 

    // Determine socket type 

    BOOL preferIPv6 = (config & kPreferIPv6) ? YES : NO; 

    BOOL useIPv6 = ((preferIPv6 && address6) || (address4 == nil)); 

    // Create the socket 

    int socketFD; 
    NSData *address; 
    NSData *connectInterface; 

    if (useIPv6) 
    { 
     LogVerbose(@"Creating IPv6 socket"); 

     socket6FD = socket(AF_INET6, SOCK_STREAM, 0); 

     socketFD = socket6FD; 
     address = address6; 
     connectInterface = connectInterface6; 
    } 
    else 
    { 
     LogVerbose(@"Creating IPv4 socket"); 

     socket4FD = socket(AF_INET, SOCK_STREAM, 0); 

     socketFD = socket4FD; 
     address = address4; 
     connectInterface = connectInterface4; 
    } 

    if (socketFD == SOCKET_NULL) 
    { 
     if (errPtr) 
      *errPtr = [self errnoErrorWithReason:@"Error in socket() function"]; 

     return NO; 
    } 

    // Bind the socket to the desired interface (if needed) 

    if (connectInterface) 
    { 
     LogVerbose(@"Binding socket..."); 

     if ([[self class] portFromAddress:connectInterface] > 0) 
     { 
      // Since we're going to be binding to a specific port, 
      // we should turn on reuseaddr to allow us to override sockets in time_wait. 

      int reuseOn = 1; 
      setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn)); 
     } 

     const struct sockaddr *interfaceAddr = (const struct sockaddr *)[connectInterface bytes]; 

     int result = bind(socketFD, interfaceAddr, (socklen_t)[connectInterface length]); 
     if (result != 0) 
     { 
      if (errPtr) 
       *errPtr = [self errnoErrorWithReason:@"Error in bind() function"]; 

      return NO; 
     } 
    } 

    // Prevent SIGPIPE signals 

    int nosigpipe = 1; 
    setsockopt(socketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe)); 

    // Start the connection process in a background queue 

    int aStateIndex = stateIndex; 
    __weak GCDAsyncSocket *weakSelf = self; 

    dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_async(globalConcurrentQueue, ^{ 
    #pragma clang diagnostic push 
    #pragma clang diagnostic warning "-Wimplicit-retain-self" 

     int result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]); 

     __strong GCDAsyncSocket *strongSelf = weakSelf; 
     if (strongSelf == nil) return_from_block; 

     if (result == 0) 
     { 
      dispatch_async(strongSelf->socketQueue, ^{ @autoreleasepool { 

       [strongSelf didConnect:aStateIndex]; 
      }}); 
     } 
     else 
     { 
      NSError *error = [strongSelf errnoErrorWithReason:@"Error in connect() function"]; 

      dispatch_async(strongSelf->socketQueue, ^{ @autoreleasepool { 

       [strongSelf didNotConnect:aStateIndex error:error]; 
      }}); 
     } 

    #pragma clang diagnostic pop 
    }); 

    LogVerbose(@"Connecting..."); 

    return YES; 
} 
이 방법을 시도 .. 연결되지 않습니다
+0

어떻게 stateIndex를 얻을 수 있습니까? 선언되지 않은 식별자 'stateIndex'의 사용 – iOS

+0

int stateIndex = 0; –

+0

이 링크에서 xmpp 프레임 워크를 다운로드 할 수 있습니다 - https://www.dropbox.com/s/iobkfdjy2q0png5/XMPP.zip?dl=0 –