草庐IT

iphone - GKSession peer disconnect 导致其他 peers 看起来断开连接

coder 2024-01-13 原文

我的应用程序使用 GKSession 和 GKSessionModePeer。它必须处理任意连接和断开连接的点,因为这是一个长时间运行的应用程序,用户应该能够进入后台并稍后返回。这在大多数情况下都很好用。但有时,当对等点断开连接时,其他设备会收到 didChangeState:GKPeerStateDisconnected 通知,不仅是真正断开连接的设备,还有其他实际上仍处于连接状态的设备。

我可以使用下面的代码和 4 台设备(全部在 iOS 5 上)重现此行为。当一切按预期进行时,当设备 A 退出应用程序时,所有其他设备都会收到通知,并且这些设备上的日志输出为:

服务:didChangeState:peer A 断开连接 (12345)

但过了一段时间,当一个设备断开连接时(再说一次 A),其他设备将获得未断开连接的设备的额外回调。例如,设备 C 将获得:

Service: didChangeState: peer A disconnected (...)//expected

Service: didChangeState: peer B disconnected (...)//never disconnected

大约在同一时间,我有时会在断开连接的设备的日志中看到此类消息,不清楚它们是否真的相关:

dnssd_clientstub 使用 NULL DNSServiceRef 调用 DNSServiceRefDeallocate

和/或

dnssd_clientstub 使用没有 ProcessReply 函数的 DNSServiceRef 调用 DNSServiceProcessResult

一旦发生这种情况,GKSession 似乎处于不良状态并且不再正确处理连接和断开连接。为了恢复到良好状态,我必须在所有设备上强行终止该应用程序,稍等片刻,然后重新开始。

在进入后台时,我尝试了多种处理 GKSession 的方法(仅设置 available=NO 并且不断开连接,根本不做任何事情),但没有一种方法效果更好。

有没有其他人遇到过这种行为(并解决了)?

AppDelegate 中的简单重现案例(使用 arc):

- (void)startGKSession 
{
    self.gkSession = [[GKSession alloc] initWithSessionID:nil displayName:nil sessionMode:GKSessionModePeer];
    gkSession.disconnectTimeout = 10;
    gkSession.delegate = self;
        gkSession.available = YES;
}

- (void)shutdownGKSession 
{
    gkSession.available = NO;
    [gkSession disconnectFromAllPeers];
    gkSession.delegate = nil;    
    gkSession = nil;
    [self.connectedDevices removeAllObjects];
}

- (void)connectToPeer:(NSString *)peerId 
{
    [gkSession connectToPeer:peerId withTimeout:10];
}

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

        switch (state) {
                case GKPeerStateAvailable:
            NSLog(@"Service: didChangeState: peer %@ available, connecting (%@)", [session displayNameForPeer:peerId], peerId);
            [self performSelector:@selector(connectToPeer:) withObject:peerId afterDelay:.5];            
                        break;

                case GKPeerStateUnavailable:
                        NSLog(@"Service: didChangeState: peer %@ unavailable (%@)", [session displayNameForPeer:peerId], peerId);
                        break;

                case GKPeerStateConnected:
            NSLog(@"Service: didChangeState: peer %@ connected (%@)", [session displayNameForPeer:peerId], peerId);
                        break;

                case GKPeerStateDisconnected:
                        NSLog(@"Service: didChangeState: peer %@ disconnected (%@)", [session displayNameForPeer:peerId], peerId);
                        break;

                case GKPeerStateConnecting:
                        NSLog(@"Service: didChangeState: peer %@ connecting (%@)", [session displayNameForPeer:peerId], peerId);
                        break;
        }
}

- (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID 
{
    [session acceptConnectionFromPeer:peerID error:nil];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.connectedDevices = [[NSMutableArray alloc] init];
    [self startGKSession];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{    
    [self shutdownGKSession];
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [self startGKSession];
}

@end

最佳答案

我从 Apple 支持人员那里听说,这种断开连接行为的发生是因为设备“通过”彼此连接。例如,设备 A 通过设备 B 连接到设备 C。如果设备 B 掉线,设备 A 会看到设备 C 断开并立即重新连接。我还没有听说这个问题是否/何时会得到解决。

关于iphone - GKSession peer disconnect 导致其他 peers 看起来断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8378169/

有关iphone - GKSession peer disconnect 导致其他 peers 看起来断开连接的更多相关文章

  1. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  3. ruby - 调用其他方法的 TDD 方法的正确方法 - 2

    我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent

  4. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  5. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

    我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

  6. ruby - 从另一个私有(private)方法中使用 self.xxx() 调用私有(private)方法 xxx,导致错误 "private method ` xxx' called” - 2

    我正在尝试获得良好的Ruby编码风格。为防止意外调用具有相同名称的局部变量,我总是在适当的地方使用self.。但是现在我偶然发现了这个:classMyClass上面的代码导致错误privatemethodsanitize_namecalled但是当删除self.并仅使用sanitize_name时,它会起作用。这是为什么? 最佳答案 发生这种情况是因为无法使用显式接收器调用私有(private)方法,并且说self.sanitize_name是显式指定应该接收sanitize_name的对象(self),而不是依赖于隐式接收器(也是

  7. ruby - 为什么 return 关键字会导致我的 'if block' 出现问题? - 2

    下面的代码工作正常:person={:a=>:A,:b=>:B,:c=>:C}berson={:a=>:A1,:b=>:B1,:c=>:C1}kerson=person.merge(berson)do|key,oldv,newv|ifkey==:aoldvelsifkey==:bnewvelsekeyendendputskerson.inspect但是如果我在“ifblock”中添加return,我会得到一个错误:person={:a=>:A,:b=>:B,:c=>:C}berson={:a=>:A1,:b=>:B1,:c=>:C1}kerson=person.merge(berson

  8. ruby-on-rails - 什么会导致与 APNS 的连接间歇性断开连接? - 2

    我有一个ruby​​脚本可以打开与Apple推送服务器的连接并发送所有待处理的通知。我看不出任何原因,但当Apple断开我的脚本时,我遇到了管道损坏错误。我已经编写了我的脚本来适应这种情况,但我宁愿只是找出它发生的原因,这样我就可以在第一时间避免它。它不会始终根据特定通知断开连接。它不会以特定的字节传输大小断开连接。一切似乎都是零星的。您可以在单个连接上发送的数据传输或有效负载计数是否有某些限制?看到人们的解决方案始终保持一个连接打开,我认为这不是问题所在。我看到连接在3次通知后断开,我看到它在14次通知后断开。我从未见过它能超过14点。有没有人遇到过这种类型的问题?如何处理?

  9. ruby - 如何断开现有的 ruby​​ 续集与数据库的连接? - 2

    我的意思是之前建立的那个DB=Sequel.sqlite('my_blog.db')或DB=Sequel.connect('postgres://user:password@localhost/my_db')或DB=Sequel.postgres('my_db',:user=>'user',:password=>'password',:host=>'localhost')等等。Sequel::Database类没有名为“disconnect”的公共(public)实例方法,尽管它有一个“connect”。也许有人已经遇到过这个问题。我将不胜感激。 最佳答案

  10. ruby-on-rails - 致命 : Peer authentication failed for user "rails" - 2

    我正在尝试运行rakedb:create在DigitalOcean服务器上使用postgresql。但是,它返回错误Peerauthenticationfailedforuser"rails",引用config/database.yml登录凭据的存储位置奇怪的是,当我通过SSH登录服务器时,这些凭据以纯文本形式显示给我。我都试过了密码以纯文本形式显示给我,同样的事情发生了。环境在生产中,我必须手动强制执行,因为应用程序在启动时正在开发中并强制它在config/environments.rb中更改不工作。如果我不得不猜测,我可能会说环境中发生了一些有趣的事情,因为DigitalOcean

随机推荐