I have a couple of NSStreams (in & out TLS) to a server, I can send and receive data via them just fine but after a while maybe 5 minutes after without any traffic, connection seems to be closed on it's own but my delegate does not called with NSStreamEventEndOccured and I only get NSStreamEventErrorOccurred AFTER I try to send something.
COnnection shouldn't close on it's own in the first place because
-app is still active
-device is not locked
-wifi it's using does not disconnect
-Remote server has a long tcp lifetime and SO_KEEPALIVE flag active, iPhone side also SO_KEEPALIVE active on it's native socket handles.
Still, I'm more concerned about why doesn't my delegate get called than my connection getting closed.
Any ideas?
Thanks
Related
I'm trying to determine if a client has closed a socket connection from netty. Is there a way to do this?
On a usual case where a client closes the socket via close() and the TCP closing handshake has been finished successfully, a channelInactive() (or channelClosed() in 3) event will be triggered.
However, on an unusual case such as where a client machine goes offline due to power outage or unplugged LAN cable, it can take a lot of time until you discover the connection was actually down. To detect this situation, you have to send some message to the client periodically and expect to receive its response within a certain amount of time. It's like a ping - you should define a periodic ping and pong message in your protocol which practically does nothing but checking the health of the connection.
Alternatively, you can enable SO_KEEPALIVE, but the keepalive interval of this option is usually OS-dependent and I would not recommend using it.
To help a user implement this sort of behavior relatively easily, Netty provides ReadTimeoutHandler. Configure your pipeline so that ReadTimeoutHandler raises an exception when there's no inbound traffic for a certain amount of time, and close the connection on the exception in your exceptionCaught() handler method. If you are the party who is supposed to send a periodic ping message, use a timer (or IdleStateHandler) to send it.
If you are writing a server, and netty is your client, then your server can detect a disconnect by calling select() or equivalent to detect when the socket is readable and then call recv(). If recv() returns 0 then the socket was closed gracefully by the client. If recv() returns -1 then check errno or equivalent for the actual error (with few exceptions, most errors should be treated as an ungraceful disconnect). The thing about unexpected disconnects is that they can take a long time for the OS to detect, so you would have to either enable TCP keep-alives, or require the client to send data to the server on a regular basis. If nothing is received from the client for a period of time then just assume the client is gone and close your end of the connection. If the client wants to, it can then reconnect.
If you read from a connection that has been closed by the peer you will get an end-of-stream indication of some kind, depending on the API. If you write to such a connection you will get an IOException: 'connection reset'. TCP doesn't provide any other way of detecting a closed connection.
TCP keep-alive (a) is off by default and (b) only operates every two hours by default when enabled. This probably isn't what you want. If you use it and you read or write after it has detected that the connection is broken, you will get the reset error above,
It depends on your protocol that you use ontop of netty. If you design it to support ping-like messages, you can simply send those messages. Besides that, netty is only a pretty thin wrapper around TCP.
Also see this SO post which describes isOpen() and related. This however does not solve the keep-alive problem.
The Arduino Ethernet (board or shield) supports a maximum of 4 connections. If acting as a server, it is very easy to cause a denial of service: just open 4 connections to the Arduino without sending any data. The server code will never realize that connections were established, as the EthernetServer::available() method only returns an EthernetClient when the connection has data available. The connections will thus remain open for as long as the client maintains them, preventing the Arduino from processing other requests, without an opportunity for the server to close them after some time.
So the question is: is there a way to set a timeout on idle connections, maybe at the Wiznet chip level?
As background information, the GET HTTP model of a dialog is called "stateless" what this means is that the connection can be closed and then re-opened with no loss of information.
However, there is an HTTP keyword where the browser can ask to keep a connection open.
The server is allowed to close a connection, in fact HTTP/1.1 defines a message from the server to browser that does just that.
So, in an Arduino where you control all of the software (TCP/IP stack and server code), then you should be to modify the WizNEt libs or add your own wrappers that time-out a dialog and close it, independent of what the browser is doing.
Thus, no DNS (or at least the keep the line open style of DNS).
Get the HTTP/1.1 spec (it is on the web) for more information and specifics.
Using QuickFixN, if I restart my trading application I occasionally am unable to logon, getting a "an existing connection was forcibly closed by the remote host" error.
The QuickFix engine retries to connect every 30secs, but always gets the same error.
If I close my application and re-open, it will connect correctly.
Speaking to my broker, it seems that they are rejecting my logins because they did not recognize my connection as being closed first time. 2nd time around, me forcing the application to close will tear-down the TCP connection, meaning that 3rd time logins work.
So my question is: is there a way to close and re-open the TCP connection without restarting the application?
Sounds like the problem is kinda on their end. Since the problem happens when you don't formally log out (e.g crash or abnormal termination), that means that their implementation apparently doesn't recognize the TCP termination.
At a higher-than-TCP layer, their FIX engine should somewhat compensate. If a few heartbeat durations occur after your disconnect, their implementation should realize you're not there anymore, since you're not responding to heartbeats.
So, neither their low-layer TCP handlers nor their FIX engine are able to set the right flag somewhere in their system that says you've gone offline. That's weird. I don't see what you can do about that, aside from intentionally doing a startup/shutdown to kludge their state flag for you.
I'm usually really hesitant to blame the other side (especially because I run the QF/n project), but that's where I'm at with the information provided.
I would want to send a message from the server actively, such as using UDP/TCPIP to a client using an arduino. It is known that this is possible if the user has port forward the specific port to the device on local network. However I wouldn't want to have the user to port forward manually, perhaps using another protocol, will this be possible?
1 Arduino Side
I think the closest you can get to this is opening a connection to the server from the arduino, then use available to wait for the server to stream some data to the arduino. Your code will be polling the open connection, but you are avoiding all the back and forth communications to open and close the connection, passing headers back and forth etc.
2 Server Side
This means the bulk of the work will be on the server side, where you will need to manage open connections so you can instantly write to them when a user triggers some event which requires a message to be pushed to the arduino. How to do this varies a bit depending on what type of server application you are running.
2.1 Node.js "walk-through" of main issues
In Node.js for example, you can res.write() on a connection, without closing it - this should give a similar effect as having an open serial connection to the arduino. That leaves you with the issue of managing the connection - should the server periodically check a database for messages for the arduino? That simply removes one link from the arduino -> server -> database polling link, so we should be able to do better.
We can attach a function triggered by the event of a message being added to the database. Node-orm2 is a database Object Relational Model driver for node.js, and it offers hooks such as afterSave and afterCreate which you can utilize for this type of thing. Depending on your application, you may be better off not using a database at all and simply using javascript objects.
The only remaining issue then, is: once the hook is activated, how do we get the correct connection into scope so we can write to it? Well you can save all the relevant data you have on the request to some global data structure, maybe a dictionary with an arduino ID as index, and in the triggered function you fetch all the data, i.e. the request context and you write to it!
See this blog post for a great example, including node.js code which manages open connections, closing them properly and clearing from memory on timeout etc.
3 Conclusion
I haven't tested this myself - but I plan to since I already have an existing application using arduino and node.js which is currently implemented using normal polling. Hopefully I will get around to it soon and return here with results.
Typically in long-polling (from what I've read) the connection is closed once data is sent back to the client (arduino), although I don't see why this would be necessary. I plan to try keeping the same connection open for multiple messages, only closing after a fixed time interval to re-establish the connection - and I hope to set this interval fairly high, 5-15 minutes maybe.
We use Pubnub to send notifications to a client web browser so a user can know immediately when they have received a "message" and stuff like that. It works great.
This seems to have the same constraints that you are looking at: No static IP, no port forwarding. User can theoretically just plug the thing in...
It looks like Pubnub has an Arduino library:
https://github.com/pubnub/arduino
So I have signalr working all fine, pushing my data to the client no problems. I implemented my own keep alive using an ajax call to keep the connection alive. But I have been reading and there is the option that I am trying:
GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(30);
But my issue is if it fails to send the keep alive how do you capture it on the javascript end?
If this is the server pushing data to keep the connection alive does that mean the client will never know if it has failed?
Or will the javascript throw a connection.error?
I want to be able to pull the clients network cable out, and after XX seconds it display a message saying network connection lost. Atm I have this working using my ajax call but is this possible using the keepalive value?
This is already implemented for every transport except LongPolling.
By default the JS client will go into reconnecting if it has missed 2 keep alives.
If you want to tie into the reconnecting event you can do:
$.connection.hub.reconnecting(function() {
// Your logic
});
If you want to tie into the event that indicates that the connection MAY go into reconnecting can do:
$.connection.hub.connectionSlow(function() {
// Your logic
});
Keep in mind by default the client will stop trying to reconnect after a given time and will shift into the disconnected state to avoid unnecessary reconnect events. If you want to ensure that your connection is ALWAYS connected, even if there's down time see my answer here: Client Reconnection