I am writing code to support APNs communication on a server. I am anticipating push notifications to be triggered frequently. Is there ever a reason I should intentionally close my connection with APNs and reopen later? e.g. If there happens to be ~1 minute break between any notification.
Related
I am setting up an MQTT/Websockets server, my client is an flutter app, which connects to the broker on main screen, and in other screens it sends and receive messages from the broker. My understanding of keepAlive is how often the client and server should share ping/pong, so they make sure the connection is still alive. being said, if my flutter app, connects to the broker in main screen, of 3600/1 hour keepAlive, and suppose to share and receive messages on other screens, if i disconnect the client from the internet for 2 minutes, and reconnect after that, it will not send/receive messages, maybe my understanding of keepAlive is not correct. Well, How would i structure my app/server to reconnect automatically to the internet as soon as internet connection is back and up again.
I have also tried On.Disconnect method, which i noticed it will never get called, and the app even though still thinks its connected to the broker.
I mentioned websockets, on the tags as i could do mqtt over websockets.
I see that no-one else has responded, so I'll try (however I'm new to this also).
Also, have you looked at the Flutter connectivity package?
From my reading of the Mqtt specification, it seems the Mqtt client ** should** disconnect the TCP/IP connection if it doesn't receive a PINGRESP to its PINGREQ in the keep alive period (ie it's not required to disconnect).
My Flutter + Mqtt app checks the connection state, and reconnects if needed, every time it sends a message. I haven't needed to check for internet dropouts, but I have noticed the connection is lost on some application state changes. The main app widget. is notified of these using didChangeAppLifecycleState() and sends a dummy message if needed.
So this doesn't answer exactly what you asked, but I hope it's useful anyway.
When a phone browser has an open connection, and the user locks the screen, then at a certain point they will no longer have a WebSocket connection.
What events are fired when this happens? Is the WebSocket.onerror or WebSocket.onclose handler called, and if so, does this happen when the screen locks/the app is suspended, or when the app comes back up again?
(And bonus question: is this standardised, or do browsers behave differently, and if so, how?)
I've done some testing myself, and the answer seems to be: no events are fired. Although the connection does drop, no error or close events are fired, not even when the browser comes back up. Therefore, the main way to deal with this appears to be to periodically check the connection status, and reconnect if need be - with exponential back-off in case the connection drops server-side. (Or to have a library do this for you, though I haven't found a properly maintained client-side browser-based WebSocket library that does this yet.)
This seems corroborated by the author of this article:
Mobile devices introduce a new category of connection issues; if a mobile device is locked, goes to sleep or the application is moved to the background, an active WebSocket connection may become unresponsive and not close itself properly.
I have read many articles on real-time push notifications. And the resume is that websocket is generally the preferred technique as long as you are not concerned about 100% browser compatibility. And yet, one article states that
Long polling - potentially when you are exchanging single call with
server, and server is doing some work in background.
This is exactly my case. The user presses a button which initiates some complex calculations on server-side, and as soon as the answer is ready, the server sends a push-notification to the client. The question is, can we say that for the case of one-time responses, long-polling is better choice than websockets?
Or unless we are concerned about obsolete browsers support and if I am going to start the project from scratch, websockets should ALWAYS be preferred to long-polling when it comes to push-protocol ?
The question is, can we say that for the case of one-time responses,
long-polling is better choice than websockets?
Not really. Long polling is inefficient (multiple incoming requests, multiple times your server has to check on the state of the long running job), particularly if the usual time period is long enough that you're going to have to poll many times.
If a given client page is only likely to do this operation once, then you can really go either way. There are some advantages and disadvantages to each mechanism.
At a response time of 5-10 minutes you cannot assume that a single http request will stay alive that long awaiting a response, even if you make sure the server side will stay open that long. Clients or intermediate network equipment (proxies, etc...) just make not keep the initial http connection open that long. That would have been the most efficient mechanism if you could have done that. But, I don't think you can count on that for a random network configuration and client configuration that you do not control.
So, that leaves you with several options which I think you already know, but I will describe here for completeness for others.
Option 1:
Establish websocket connection to the server by which you can receive push response.
Make http request to initiate the long running operation. Return response that the operation has been successfully initiated.
Receive websocket push response some time later.
Close webSocket (assuming this page won't be doing this again).
Option 2:
Make http request to initiate the long running operation. Return response that the operation has been successfully initiated and probably some sort of taskID that can be used for future querying.
Using http "long polling" to "wait" for the answer. Since these requests will likely "time out" before the response is received, you will have to regularly long poll until the response is received.
Option 3:
Establish webSocket connection.
Send message over webSocket connection to initiate the operation.
Receive response some time later that the operation is complete.
Close webSocket connection (assuming this page won't be using it any more).
Option 4:
Same as option 3, but using socket.io instead of plain webSocket to give you heartbeat and auto-reconnect logic to make sure the webSocket connection stays alive.
If you're looking at things purely from the networking and server efficiency point of view, then options 3 or 4 are likely to be the most efficient. You only have the overhead of one TCP connection between client and server and that one connection is used for all traffic and the traffic on that one connection is pretty efficient and supports actual push so the client gets notified as soon as possible.
From an architecture point of view, I'm not a fan of option 1 because it just seems a bit convoluted when you initiate the request using one technology and then send the response via another and it requires you to create a correlation between the client that initiated an incoming http request and a connected webSocket. That can be done, but it's extra bookkeeping on the server. Option 2 is simple architecturally, but inefficient (regularly polling the server) so it's not my favorite either.
There is an alterternative that don't require polling or having an open socket connection all the time.
It's called web push.
The Push API gives web applications the ability to receive messages pushed to them from a server, whether or not the web app is in the foreground, or even currently loaded, on a user agent. This lets developers deliver asynchronous notifications and updates to users that opt in, resulting in better engagement with timely new content.
Some perks are
You need to ask for notification permission
Your site needs to have a service worker running in foreground
having a service worker also means you need to have SSL / HTTPS
The scenario i have been testing is trying to cancel a requested session initiation before an answer from the remote. I am using a setup between two Nexus 7 devices running Android 6.0.
I introduced a session initiation cancel option which is available to the user during the period that a session initiation request has been made and the remote user has not yet answered (e.g., in a user alerting state). The RTC peer connection signaling state on the initiating side is "have-local-offer", when the user requests the session cancel. On initiation of the cancel, i invoke a close on the peer connection and see that a signaling state change occurs on the initiation side as the RTC signaling state goes (as i would expect) to 'close'.
On the side receiving the session initiation request, however, the RTC signaling state goes to the state "have-remote-offer" as expected, but the close event from the initiating side does not appear to propagate to the receiving side, and the receiving side remains in the "have-remote-offer" state.
I have reviewed the standards and it appears that the event should be generated on the receiving side (i.e., the close should be sent when closed in state "have local offer").
Obviously, i can build around this case and generate a terminate over the session server signaling channel - but would like to understand whether i am doing something wrong or mis-interpreting the spec?
thanks,
You haven't successfully negotiated a connection yet, so RTCPeerConnection's only means of communication to the other side is through the signaling channel you provide.
For it to communicate something on close, that something would have to be surfaced in the API akin to onicecandidate, and no such thing exists.
Remember, your code is on both ends, so you can easily signal this yourself.
One minor mistake in the specification aside (which will hopefully go away soon), a peer connection does not close itself.
I would like to do some one way streaming of data and am experimenting with SSE vs Websockets.
Using SSE form a golang server I'm finding it confusing on how to notify the client when sessions are finished. (eg the server has finished sending the events or the server suddenly goes offline or client looses connectivity)
One thing I need is to reliably know when these disconnect situations. Without using timeouts etc.
My experiments so far , when I take the server offline the client gets EOF. But I'm having trouble trying to figure out how to signal from the server to the client that a connection is closed / finished and then how to handle / read it? Is EOF a reliable way to determine a closed / error / finished state?
Many of the examples with SSE fail to show client good client connection handling.
Would this be easier with Websockets?
Any experiences suggestions most appreciated.
Thanks
The SSE standard requires that the browser reconnect, automatically, after N seconds, if the connection is lost or if the server deliberately closes the socket. (N defaults to 5 in Firefox, 3 in Chrome and Safari, last time I checked.) So, if that is desirable, you don't need to do anything. (In WebSockets you would have to implement this kind of reconnect for yourself.)
If that kind of reconnect is not desirable, you should instead send a message back to the client, saying "the show is over, go away". E.g. if you are streaming financial data, you might send that on a Friday evening, when the markets shut. The client should then intercept this message and close the connection from its side. (The socket will then disappear, so the server process will automatically get closed.)
In JavaScript, and assuming you are using JSON to send data, that would look something like:
var es = EventSource("/datasource");
es.addEventListener("message", function(e){
var d = JSON.parse(e.data);
if(d.shutdownRequest){
es.close();
es=null;
//Tell user what just happened.
}
else{
//Normal processing here
}
},false);
UPDATE:
You can find out when the reconnects are happening, by listening for the "close" event, then looking at the e.target.readyState
es.addEventListener("error", handleError, false);
function handleError(e){
if(e.target.readyState == 0)console.log("Reconnecting...");
if(e.target.readyState == 2)console.log("Giving up.");
}
No other information is available, but more importantly it cannot tell the difference between your server process deliberately closing the connection, your web server crashing, or your client's internet connection going down.
One other thing you can customize is the retry time, by having the the server send a retry:NN message. So if you don't want quick reconnections, but instead want at least 60 seconds between any reconnect attempts do this have your server send retry:60.