我在后端使用带有Twisted Server的iOS消息应用程序使用GCDAsyncSocket库。一切都设置得很好,工作正常,但我发现一个特殊的情况,当它没有正常工作。因此,我的服务器的架构是这样的:当用户离线时,他的所有消息都缓存在服务器上,当他在线检测到时,服务器立即向他发送所有缓存的待处理消息。
现在,GCDAsyncSocket使用内部读写队列,所以在这里,服务器发送的待处理消息由读取队列排队,直到它们被委托方法-(void)socket:didReadData:withTag:
读取。现在,在我的app,此委托方法处理传入的消息并逐个显示在tableview中。因此,问题的关键是每当委托方法从队列中读取时,如果挂起应用程序,则读取队列中的所有未处理消息都将丢失。因此,为了解决这个问题,我想访问读取队列,以便在应用程序暂停之前保存其内容,以便在再次打开应用程序时可以恢复它。
注意:根据我的理解,丢失的邮件来自队列而不是服务器,因为服务器显示"发送的所有邮件"甚至在代理在处理时到达一半的消息之前。如果暂停,那么此问题仍然存在。
我这样做是错误的吗?或者有没有办法访问队列?
答案 0 :(得分:3)
您可以考虑在协议中添加确认步骤。而不是让服务器发送所有排队的消息然后立即忘记它们,您可以让它记住它们,直到客户端发回每条消息确认。
这样,无论客户端在接收特定消息和将其显示给用户之间做了什么,该消息始终可用于从服务器重新传递。只有在客户端查看(并因此确认)该消息后,服务器才会忘记它(因此在下次客户端显示时不会将其重新传输到客户端)。
您可以通过为邮件分配唯一标识符来轻松完成此操作。这些可能是随机UUID或 - 如果您的消息传递必须始终按顺序 - 序列号。序列号很方便(如果它们对您的应用程序有意义),因为通过确认单个消息序列号,您的客户端可以指示它已经处理了多个消息(因为如果它总是按顺序处理它们,那么任何具有较早序列号的消息必须具有已经处理过了。)
此策略的失败模式与当前策略的失败模式相反。现在,当手机在从接收队列中拉出消息之前暂停时,它将丢失。使用确认,消息在处理(显示)之前不会丢失。但是,您可能会显示该消息,然后无法以某种方式发送确认。这将导致消息显示两次。
您还可以通过在手机上记录有关已处理(显示)哪些消息的信息来缩小此故障的窗口。如果手机收到来自服务器的消息,它知道它已经显示,那么它可以跳过显示它,只是重新发送确认以允许服务器忘记它。
这会将故障窗口减少到显示消息和本地记录消息显示之间的时间(或者相反的顺序,如果您更喜欢故障模式,消息丢失而不是它们显示两次)。