我尝试了所有的code.i使用此代码允许连接ipv6网络连接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网络中正常工作但是没有连接ipv6.if我使用这个代码而不是连接ipv4.please帮助我。我想连接两个网络..
答案 0 :(得分: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;
}