简体   繁体   English

访问GCDAsyncSocket读取队列

[英]Access GCDAsyncSocket read queue

I'm using GCDAsyncSocket library for my iOS messaging app with Twisted Server in the backend. 我在我的iOS消息应用程序中使用GCDAsyncSocket库与后端的Twisted Server。 Everything is setup fine and works fine, but I found out about a peculiar situation when it doesn't work fine. 一切都设置得很好,工作正常,但我发现一个特殊的情况,当它不能正常工作。 So, my server is architectured in such a way that when the user is offline, all his message are cached on server and when he's detected online, the server sends to him all his cached pending messages at once. 因此,我的服务器的架构是这样的:当用户离线时,他的所有消息都缓存在服务器上,当他在网上检测到时,服务器立即向他发送所有缓存的待处理消息。

Now, GCDAsyncSocket uses internal read and write queues, so here, those sent pending-messages by the server are queued by the read queue until they're read by the delegate method -(void)socket:didReadData:withTag: Now, in my app, this delegate method processes the incoming messages and displays them in a tableview one by one. 现在,GCDAsyncSocket使用内部读写队列,所以在这里,服务器发送的待处理消息被读取队列排队,直到它们被委托方法读取-(void)socket:didReadData:withTag:现在,在我的app,此委托方法处理传入的消息并逐个显示在tableview中。 So, the point of problem is that whenever the delegate method is reading from the queue, if you suspend the app, all the unprocessed messages in the read queue are lost. 因此,问题的关键是每当委托方法从队列中读取时,如果挂起应用程序,则读取队列中的所有未处理消息都将丢失。 So to counter this, I want to access the read queue so that I can save its contents before app suspension so that I can recover it when app is opened again. 所以为了解决这个问题,我想访问读取队列,以便我可以在应用程序暂停之前保存其内容,这样我可以在再次打开应用程序时恢复它。

Note : As per my understanding, the lost messages are from the queue and not the server because the server shows "all messages sent" even before the delegate reaches half of the messages while processing. 注意 :根据我的理解,丢失的消息来自队列而不是服务器,因为服务器显示“所有消息已发送”,甚至在代理在处理时到达一半消息之前。 And after that if suspended, then this problem persists. 之后,如果暂停,那么这个问题仍然存在。

So am I doing it the wrong way? 我这样做是错误的吗? Or is there any way to access the queue? 或者有没有办法访问队列?

You could consider adding an acknowledgement step to your protocol. 您可以考虑在协议中添加确认步骤。 Instead of letting the server send all queued messages and then immediately forget them, you could have it remember them until the client sends back a per-message acknowledgement. 而不是让服务器发送所有排队的消息然后立即忘记它们,您可以让它记住它们,直到客户端发回每个消息确认。

This way, no matter what the client does between receiving a particular message and displaying it to the user, that message will always be available for re-delivery from the server. 这样,无论客户端在接收特定消息和将其显示给用户之间做了什么,该消息将始终可用于从服务器重新传递。 Only after the client has viewed (and therefore acknowledged) the message will the server forget it (and thus not re-transmit it to the client the next time the client shows up). 只有在客户端查看(并因此确认)该消息后,服务器才会忘记它(因此在下次客户端显示时不会将其重新发送到客户端)。

You can do this pretty easily by assigning unique identifiers to messages. 通过为消息分配唯一标识符,您可以非常轻松地完成此操作。 These might be random UUIDs or - if your message deliver must always be in order - sequence numbers. 这些可能是随机UUID或 - 如果您的消息传递必须始终按顺序 - 序列号。 Sequence numbers are convenient (if they make sense for your application) because by acknowledging a single message sequence number your client can indicate that it has processed several messages (because if it always processes them in order then any message with an earlier sequence number must have been processed too). 序列号很方便(如果它们对您的应用程序有意义),因为通过确认单个消息序列号,您的客户端可以指示它已经处理了多个消息(因为如果它总是按顺序处理它们,那么任何具有较早序列号的消息必须具有已被处理)。

The failure mode for this strategy is the opposite as the failure mode for your current strategy. 此策略的故障模式与当前策略的故障模式相反。 Now, when the phone suspends before a message is pulled from the receive queue, it is lost. 现在,当手机在从接收队列中拉出消息之前暂停时,它将丢失。 Using acknowledgements, the message cannot be lost until it has been processed (displayed). 使用确认,消息在处理(显示)之前不会丢失。 However, you might display the message and then fail to send the acknowledgement somehow. 但是,您可能会显示该消息,然后无法以某种方式发送确认。 This will lead to a message being displayed twice. 这将导致消息显示两次。

You can narrow the window for this failure by also recording information on the phone about which messages have been processed (displayed). 您还可以通过在手机上记录有关已处理(显示)哪些消息的信息来缩小此故障的窗口。 If the phone receives a message from the server that it knows it has already displayed then it can skip displaying it and just re-send the acknowledgement to allow the server to forget it. 如果手机收到来自服务器的消息,它知道它已经显示,那么它可以跳过显示它,只是重新发送确认以允许服务器忘记它。

This reduces the failure window to just the time between when you display a message and when you manage to record locally that that message has been displayed (or the opposite order, if you prefer the failure mode where messages are lost rather than where they are displayed twice). 这会将故障窗口减少到显示消息和本地记录消息显示之间的时间(或者相反的顺序,如果您更喜欢故障模式,消息丢失而不是显示消息的位置)两次)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM