ipv6 的多点连接问题得不到邀请
Multipeer Connection issue with ipv6 don't get an invitation
我的应用程序被 Apple 拒绝,因为它无法连接到连接到 IPv6 网络的 Wi-Fi 上的其他设备 运行ning iOS 10.1.1。
当我点击连接时,该应用程序继续搜索被邀请者并且不会产生进一步的用户操作。
我使用 Multi-peer Connectivity 并且我从未测试过我的应用程序连接到 IPv6(这是我的第一个版本)。但是应用程序 运行 在没有任何连接或未连接到 IPv4 网络的情况下非常好。
我不知道为什么应用 运行 正在使用 IPv4 正常连接并且在 iPad 连接到 IPv6 网络时无法连接到对等点。
所以我的问题是:是否可以使用 IPv6 的多对等连接以便 Apple 可以批准该应用程序,或者我应该如何处理这个问题?
这是我的代码,可能那里有问题。
@interface ConnectionManageriOS7 () <MCSessionDelegate, MCBrowserViewControllerDelegate>
{
UILocalNotification *_expireNotification;
UIBackgroundTaskIdentifier _taskId;
}
@property (nonatomic, strong) MCSession *session;
@property (nonatomic, strong) MCPeerID *localPeerID;
@property (nonatomic, strong) MCBrowserViewController *browserVC;
@property (nonatomic, strong) MCAdvertiserAssistant *advertiser;
@end
static ConnectionManageriOS7 *_manager = nil;
@implementation ConnectionManageriOS7
+ (ConnectionManageriOS7 *)connectManager {
@synchronized([ConnectionManageriOS7 class]){
if (_manager == nil) {
_manager = [[ConnectionManageriOS7 alloc] init];
}
return _manager;
}
return nil;
}
- (id)init {
self = [super init];
if (self) {
[self setupSessionAndAdvertiser];
}
return self;
}
- (void)setupSessionAndAdvertiser {
_localPeerID = [[MCPeerID alloc] initWithDisplayName:[UIDevice currentDevice].name];;
_session = [[MCSession alloc] initWithPeer:_localPeerID];
_session.delegate = self;
}
- (void)connectWithDelegate:(id)delegate {
_delegate = delegate;
if (_session.connectedPeers.count) {
if ([_delegate respondsToSelector:@selector(didConntectedWithManager:)]) {
[_delegate didConntectedWithManager:self];
}
} else {
if (_advertiser == nil) {
_advertiser = [[MCAdvertiserAssistant alloc] initWithServiceType:VISUS_Service
discoveryInfo:nil
session:_session];
_isConnected = NO;
[_advertiser start];
}
if (_browserVC == nil) {
_browserVC = [[MCBrowserViewController alloc] initWithServiceType:VISUS_Service session:_session];
_browserVC.delegate = self;
}
[(UIViewController *)delegate presentViewController:_browserVC
animated:YES completion:nil];
}
}
- (void)sendMessage:(NSString *)message {
NSData *textData = [message dataUsingEncoding:NSASCIIStringEncoding];
NSLog(@"Send Data: %@", message);
NSError *error = nil;
[_session sendData:textData
toPeers:_session.connectedPeers
withMode:MCSessionSendDataReliable
error:&error];
if (error) {
//
[self session:_session peer:nil didChangeState:MCSessionStateNotConnected];
NSLog(@"error %@", error.userInfo);
}
}
- (void)stopService {
NSLog(@"Stop Service");
[_advertiser stop];
_advertiser = nil;
_browserVC = nil;
}
#pragma marks -
#pragma marks MCBrowserViewControllerDelegate
- (void) dismissBrowserVC{
[_browserVC dismissViewControllerAnimated:YES completion:nil];
}
// Notifies the delegate, when the user taps the done button
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController {
if ([_delegate respondsToSelector:@selector(didConntectedWithManager:)]) {
[_delegate didConntectedWithManager:self];
}
[self dismissBrowserVC];
}
// Notifies delegate that the user taps the cancel button.
- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController{
if (_browserVC == nil) {
[browserViewController dismissViewControllerAnimated:YES completion:nil];
}else {
[self dismissBrowserVC];
}
}
#pragma marks -
#pragma marks MCBrowserViewControllerDelegate
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state {
if (state != MCSessionStateConnecting) {
if (state == MCSessionStateConnected) {
_isConnected = true;
if ([_delegate respondsToSelector:@selector(willConntectedWithManager:)]) {
[_delegate willConntectedWithManager:self];
}
}
else {
_isConnected = false;
[self stopService];
if ([_delegate respondsToSelector:@selector(didDisconntectedWithManager:)]) {
[_delegate didDisconntectedWithManager:self];
}
}
}
}
// Received data from remote peer
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID{
// Decode data back to NSString
NSString *message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Receive Data: %@", message);
// append message to text box:
dispatch_async(dispatch_get_main_queue(), ^{
if ([_delegate respondsToSelector:@selector(connectionManager:receivedString:)]) {
[_delegate connectionManager:self receivedString:message];
}
});
}
- (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error {
_isConnected = false;
[self stopService];
NSLog(@"----- Error ----- %@", error.localizedDescription);
}
// Received a byte stream from remote peer
- (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID {
}
// Start receiving a resource from remote peer
- (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress {
}
- (void) session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void (^)(BOOL accept))certificateHandler
{
certificateHandler(YES);
}
- (void) createExpireNotification
{
[self killExpireNotification];
if (_session.connectedPeers.count != 0) // if peers connected, setup kill switch
{
NSTimeInterval gracePeriod = 20.0f;
// create notification that will get the user back into the app when the background process time is about to expire
NSTimeInterval msgTime = UIApplication.sharedApplication.backgroundTimeRemaining - gracePeriod;
UILocalNotification* n = [[UILocalNotification alloc] init];
_expireNotification = n;
_expireNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:msgTime];
_expireNotification.alertBody = @"Bluetooth Connectivity is about to disconnect. Open the app to resume Test";
_expireNotification.soundName = UILocalNotificationDefaultSoundName;
_expireNotification.applicationIconBadgeNumber = 1;
[UIApplication.sharedApplication scheduleLocalNotification:_expireNotification];
}
}
- (void) killExpireNotification
{
if (_expireNotification != nil)
{
[UIApplication.sharedApplication cancelLocalNotification:_expireNotification];
_expireNotification = nil;
}
}
- (void)bacgroundHandling {
_taskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
{
[self stopService];
[[UIApplication sharedApplication] endBackgroundTask:_taskId];
_taskId = UIBackgroundTaskInvalid;
}];
[self createExpireNotification];
}
- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void(^)(BOOL accept, MCSession *session))invitationHandler
{
// http://down.vcnc.co.kr/WWDC_2013/Video/708.pdf -- wwdc tutorial, this part is towards the end (p119)
// self.arrayInvitationHandler = [NSArray arrayWithObject:[invitationHandler copy]];
// ask the user
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:peerID.displayName
message:@"Would like to create a session with you"
delegate:self
cancelButtonTitle:@"Decline" otherButtonTitles:@"Accept", nil];
[alertView show];
}
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// retrieve the invitationHandler and check whether the user accepted or declined the invitation...
BOOL accept = (buttonIndex != alertView.cancelButtonIndex) ? YES : NO;
// respond
if(accept) {
// void (^invitationHandler)(BOOL, MCSession *) = [self.arrayInvitationHandler objectAtIndex:0];
// invitationHandler(accept, self.mySession);
}
else
{
NSLog(@"Session disallowed");
}
}
- (void)terminate {
[self killExpireNotification];
[self stopService];
}
@end
我已经解决了问题。对于有类似问题的每个人:
这不是 IPv6 的问题,而是如何使用 Multipeer 连接的问题。在我的案例中,我尝试使用 iPad 和模拟器进行 IPv6 连接。我用我的 Macbook 创建了 nat64 network。模拟器和 iPad 从未见过对方的原因是它们没有连接到同一个 wifi 网络。
解决方案:
只需测试两个 iPad 并使用您的 mac 作为 nat64 network 接入点。
我的应用程序被 Apple 拒绝,因为它无法连接到连接到 IPv6 网络的 Wi-Fi 上的其他设备 运行ning iOS 10.1.1。
当我点击连接时,该应用程序继续搜索被邀请者并且不会产生进一步的用户操作。
我使用 Multi-peer Connectivity 并且我从未测试过我的应用程序连接到 IPv6(这是我的第一个版本)。但是应用程序 运行 在没有任何连接或未连接到 IPv4 网络的情况下非常好。
我不知道为什么应用 运行 正在使用 IPv4 正常连接并且在 iPad 连接到 IPv6 网络时无法连接到对等点。
所以我的问题是:是否可以使用 IPv6 的多对等连接以便 Apple 可以批准该应用程序,或者我应该如何处理这个问题?
这是我的代码,可能那里有问题。
@interface ConnectionManageriOS7 () <MCSessionDelegate, MCBrowserViewControllerDelegate>
{
UILocalNotification *_expireNotification;
UIBackgroundTaskIdentifier _taskId;
}
@property (nonatomic, strong) MCSession *session;
@property (nonatomic, strong) MCPeerID *localPeerID;
@property (nonatomic, strong) MCBrowserViewController *browserVC;
@property (nonatomic, strong) MCAdvertiserAssistant *advertiser;
@end
static ConnectionManageriOS7 *_manager = nil;
@implementation ConnectionManageriOS7
+ (ConnectionManageriOS7 *)connectManager {
@synchronized([ConnectionManageriOS7 class]){
if (_manager == nil) {
_manager = [[ConnectionManageriOS7 alloc] init];
}
return _manager;
}
return nil;
}
- (id)init {
self = [super init];
if (self) {
[self setupSessionAndAdvertiser];
}
return self;
}
- (void)setupSessionAndAdvertiser {
_localPeerID = [[MCPeerID alloc] initWithDisplayName:[UIDevice currentDevice].name];;
_session = [[MCSession alloc] initWithPeer:_localPeerID];
_session.delegate = self;
}
- (void)connectWithDelegate:(id)delegate {
_delegate = delegate;
if (_session.connectedPeers.count) {
if ([_delegate respondsToSelector:@selector(didConntectedWithManager:)]) {
[_delegate didConntectedWithManager:self];
}
} else {
if (_advertiser == nil) {
_advertiser = [[MCAdvertiserAssistant alloc] initWithServiceType:VISUS_Service
discoveryInfo:nil
session:_session];
_isConnected = NO;
[_advertiser start];
}
if (_browserVC == nil) {
_browserVC = [[MCBrowserViewController alloc] initWithServiceType:VISUS_Service session:_session];
_browserVC.delegate = self;
}
[(UIViewController *)delegate presentViewController:_browserVC
animated:YES completion:nil];
}
}
- (void)sendMessage:(NSString *)message {
NSData *textData = [message dataUsingEncoding:NSASCIIStringEncoding];
NSLog(@"Send Data: %@", message);
NSError *error = nil;
[_session sendData:textData
toPeers:_session.connectedPeers
withMode:MCSessionSendDataReliable
error:&error];
if (error) {
//
[self session:_session peer:nil didChangeState:MCSessionStateNotConnected];
NSLog(@"error %@", error.userInfo);
}
}
- (void)stopService {
NSLog(@"Stop Service");
[_advertiser stop];
_advertiser = nil;
_browserVC = nil;
}
#pragma marks -
#pragma marks MCBrowserViewControllerDelegate
- (void) dismissBrowserVC{
[_browserVC dismissViewControllerAnimated:YES completion:nil];
}
// Notifies the delegate, when the user taps the done button
- (void)browserViewControllerDidFinish:(MCBrowserViewController *)browserViewController {
if ([_delegate respondsToSelector:@selector(didConntectedWithManager:)]) {
[_delegate didConntectedWithManager:self];
}
[self dismissBrowserVC];
}
// Notifies delegate that the user taps the cancel button.
- (void)browserViewControllerWasCancelled:(MCBrowserViewController *)browserViewController{
if (_browserVC == nil) {
[browserViewController dismissViewControllerAnimated:YES completion:nil];
}else {
[self dismissBrowserVC];
}
}
#pragma marks -
#pragma marks MCBrowserViewControllerDelegate
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state {
if (state != MCSessionStateConnecting) {
if (state == MCSessionStateConnected) {
_isConnected = true;
if ([_delegate respondsToSelector:@selector(willConntectedWithManager:)]) {
[_delegate willConntectedWithManager:self];
}
}
else {
_isConnected = false;
[self stopService];
if ([_delegate respondsToSelector:@selector(didDisconntectedWithManager:)]) {
[_delegate didDisconntectedWithManager:self];
}
}
}
}
// Received data from remote peer
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID{
// Decode data back to NSString
NSString *message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Receive Data: %@", message);
// append message to text box:
dispatch_async(dispatch_get_main_queue(), ^{
if ([_delegate respondsToSelector:@selector(connectionManager:receivedString:)]) {
[_delegate connectionManager:self receivedString:message];
}
});
}
- (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error {
_isConnected = false;
[self stopService];
NSLog(@"----- Error ----- %@", error.localizedDescription);
}
// Received a byte stream from remote peer
- (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID {
}
// Start receiving a resource from remote peer
- (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress {
}
- (void) session:(MCSession *)session didReceiveCertificate:(NSArray *)certificate fromPeer:(MCPeerID *)peerID certificateHandler:(void (^)(BOOL accept))certificateHandler
{
certificateHandler(YES);
}
- (void) createExpireNotification
{
[self killExpireNotification];
if (_session.connectedPeers.count != 0) // if peers connected, setup kill switch
{
NSTimeInterval gracePeriod = 20.0f;
// create notification that will get the user back into the app when the background process time is about to expire
NSTimeInterval msgTime = UIApplication.sharedApplication.backgroundTimeRemaining - gracePeriod;
UILocalNotification* n = [[UILocalNotification alloc] init];
_expireNotification = n;
_expireNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:msgTime];
_expireNotification.alertBody = @"Bluetooth Connectivity is about to disconnect. Open the app to resume Test";
_expireNotification.soundName = UILocalNotificationDefaultSoundName;
_expireNotification.applicationIconBadgeNumber = 1;
[UIApplication.sharedApplication scheduleLocalNotification:_expireNotification];
}
}
- (void) killExpireNotification
{
if (_expireNotification != nil)
{
[UIApplication.sharedApplication cancelLocalNotification:_expireNotification];
_expireNotification = nil;
}
}
- (void)bacgroundHandling {
_taskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
{
[self stopService];
[[UIApplication sharedApplication] endBackgroundTask:_taskId];
_taskId = UIBackgroundTaskInvalid;
}];
[self createExpireNotification];
}
- (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser didReceiveInvitationFromPeer:(MCPeerID *)peerID withContext:(NSData *)context invitationHandler:(void(^)(BOOL accept, MCSession *session))invitationHandler
{
// http://down.vcnc.co.kr/WWDC_2013/Video/708.pdf -- wwdc tutorial, this part is towards the end (p119)
// self.arrayInvitationHandler = [NSArray arrayWithObject:[invitationHandler copy]];
// ask the user
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:peerID.displayName
message:@"Would like to create a session with you"
delegate:self
cancelButtonTitle:@"Decline" otherButtonTitles:@"Accept", nil];
[alertView show];
}
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// retrieve the invitationHandler and check whether the user accepted or declined the invitation...
BOOL accept = (buttonIndex != alertView.cancelButtonIndex) ? YES : NO;
// respond
if(accept) {
// void (^invitationHandler)(BOOL, MCSession *) = [self.arrayInvitationHandler objectAtIndex:0];
// invitationHandler(accept, self.mySession);
}
else
{
NSLog(@"Session disallowed");
}
}
- (void)terminate {
[self killExpireNotification];
[self stopService];
}
@end
我已经解决了问题。对于有类似问题的每个人:
这不是 IPv6 的问题,而是如何使用 Multipeer 连接的问题。在我的案例中,我尝试使用 iPad 和模拟器进行 IPv6 连接。我用我的 Macbook 创建了 nat64 network。模拟器和 iPad 从未见过对方的原因是它们没有连接到同一个 wifi 网络。
解决方案:
只需测试两个 iPad 并使用您的 mac 作为 nat64 network 接入点。