I have read up on the Reachability framework and am still confused why the definition of a host is being reachable is "when a data packet... can leave the local device".
If reachability returns "yes" then it seems that I still need to try and make a socket connection and until that actually connects I do not really know my host is up. Why doesn't Reachability use a Ping to get a better idea of whether the host is actually up? And what is the need of this framework in the first place?
My guess is these two, but if anyone knows any other reasons to use the Reachability framework please let me know.
1) Reachability gives a callback which gives instant notification when the internet comes back up. When this occurs a socket connection can be immediately attempted. However in 99% of applications it seems acceptable to just attempt a socket connection every few seconds, or worst case just try to make the connection when a user does a certain action. Granted, this is not an ideal solution but I don't see why the Reachability framework would ever be really necessary for this reason.
2) Even in the case where a socket connection has been made to the server, Reachability gives an important bit of information about whether the network is G3/WiFi. I think this is the only time Reachability is really necessary because it allows optimization of behavior according to network type.
Reachability is actually quite useful: Given your case (1), you forget that it gives you notifications on both network up and down events. Meaning you can set the callback to handle events such as losing network connectivity (which happens more than you would like on both WiFi and 3G).
Additionally, testing a connection using a socket is not that straightforward; Socket operations are , by default, blocking, and though you can use asynchronous operations (or threads), doing so involves writing code. Not to mention trying DNS when the network is down, and other such issues. By setting a reachability target using the framework, you can alleviate the need to handle all sorts of issues like these yourself, and simply wait for that callback.
Hope this helps,
TG
Related
I have an iOS app that establish a peer-to-peer connection through Bonjour/NSNetService. (based on the WiTap sample code)
In some cases, both devices won’t receive data anymore after a few seconds while they are still able to write data out (i.e. without an error being reported).
The data written to the NSOutputStream never makes it to the NSInputStream of the other side.
The strange part is that sending and receiving works right after the connection is established. It seems to go bad after a few seconds.
If I set includesPeerToPeer = false it is not happening anymore. Does anyone having the same issue? I need to use peer to peer because is required to use bluetooth.
Thanks
My first guess would be that you're writing data to the stream before you get a stream event telling you that it is ready to accept more data.
If that isn't the problem, then either it's a bug in your code (which you haven't posted any of) or... well, it is possible that the class in question still doesn't work correctly. See:
https://developer.apple.com/library/ios/qa/qa1546/_index.html
If that's the case, you might have to drop down to Core Foundation briefly.
I am currently building an App using CocoaAsyncSocket. I connect to a TCP server and read/write some data.
I create the socket using
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
When data is received, I use FMDB to save it into a database. Everything works fine, until I send the App to Background (using Homebutton), and then resuming to it. The UI is frozen and not responsive, the Debugger shows, that it is waiting at semaphore_wait_trap.
Don't use the main queue as an argument to the delegateQueue parameter. Use one of the global concurrent queues or a serial/parallel queue you create yourself.
Update: I just looked at the implementation for GCDAsyncSocket and now realize that the delegate queue and methods are fired async to the actual read/write operations, which happen on an internal queue, so my suggestion was either irrelevant (depending on what you're actually doing in the completion methods) or, at the very least, not pertinent to the problem you're having. I think what's happening is that the internal socket(s) are being closed, as per the iOS App Programming Guide. To wit:
Be prepared to handle connection failures in your network-based
sockets. The system may tear down socket connections while your app
is suspended for any number of reasons. As long as your socket-based
code is prepared for other types of network failures, such as a lost
signal or network transition, this should not lead to any unusual
problems. When your app resumes, if it encounters a failure upon
using a socket, simply reestablish the connection.
The GCDAsyncSocket class you're using has some methods which seem to be aimed at dealing with this, such as -autoDisconnectOnClosedReadStream, and I think you just need to add some code to handle the disconnection / connection re-establishment case.
A little vague in the title, but I want to know what others are doing about this. I wonder:
If you use Reachability, do you perform any additional checks or are
you fully confident that the notifications will take care of
everything?
Has anyone had any issues with their WiFi working, but
Reachability returning false despite that there's an active connection? (I haven't myself, but have read about it somewhere).
I use it, and have not had any issue with reliability of detecting WiFi connectivity. It has worked fine for me when used properly.
OK - let's rephrase this whole question shall we?
Is there any way to tell if iOS is holding onto an NSURLConnection after it has finished & returned it's data?
I've got 2 NSURLConnections I'm instantiating & calling into a server with. The first one initiates the connection with the server and then goes into a COMET style long-polling wait while another user interacts with the request. The second one goes into the server and triggers a cancel mechanism which safely ends the first request and causes both to return successfully with a "Cancelled by you" message.
In the happy path case the Cancel button will never be clicked. But it's possible to click it and exit the current action.
This whole scenario works GREAT once. And then never works again (until the app is reset).
It's as though the first time thru one of the connections is never released and we are from then on limited to only a single connection because one of them is locked.
BTW I've tried NSURLConnection, AFNetwork, MKNetworkKit, ASIHTTPRequest - no luck what-so-ever with any other frameworks. NSURLConnection should do what I want. It's just ... not letting go of one of my connections.
I suspect the cancellation request in Step 2 is leaving the HTTP connection open.
I don't know exactly how the NS* classes work with respect to the HTTP/1.1 recommendation of at most two simultaneous connections, but let's assume they're enforcing at most two connections. Let's suppose the triggering code in Instance A (steps 1 and 3 of your example) cleans up after itself, but the cancellation code in Instance B (steps 2 and 4) leaves the connection open. That might explain what you are observing.
If I were you, I'd compare the code that runs in step 1 against the code that runs in step 2. I bet there's a difference between them in terms of the way they clean up after themselves.
If I'm not wrong,
iOS/Mac holds on to a NSURLConnection as long as the "Keep-Alive" header dictates it to.
But as a iOS developer you shouldn't be worried. any reason why you would like to know that?
So unfortunately with the lack of a real solution to this issue being found in all my testing I've had to implement simple polling to resolve the issue.
I've also had to implement iOS only APIs on the server.
What this comes down to is an API to send up a command and put it into a queue on the server, then using an NSTimer on the client to check the status of the of the queued item on a regular interval.
Until I can find out how to make multiple connections on iOS with long-polling this is the only working solution. Once I have a decent amount of points I'll gladly bounty them away for a solution to this :(
I am learning C and Objective-C so am still dependent on examples...
I found AsyncUDPSocket which has a lot of example code in the Google Code repository, but I'm not far enough along to understand it all yet.
I'm trying to build an iPhone app that uses UDP for communication to another device (Arduino). I have the device end working (testing with the UDP Tool app). I just need help with the iOS side of it...
An example with more explanation would really help (that is, a tutorial)... Is there one or what would some example code with good comments be?
https://github.com/robbiehanson/CocoaAsyncSocket
GCDAsyncUdpSocket and AsyncUdpSocket are UDP/IP socket networking libraries. Here are the key features available in both:
Native objective-c, fully self-contained in one class. No need to
muck around with low-level sockets. This class handles everything for
you.
Full delegate support.
Errors, send completions, receive completions, and disconnections all result in a call to your delegate method.
Queued non-blocking send and receive operations, with optional
timeouts.
You tell it what to send or receive, and it handles everything for you. Queueing, buffering, waiting and checking errno - all
handled for you automatically.
Support for IPv4 and IPv6.
Automatically send/recv using IPv4 and/or IPv6. No more worrying about multiple sockets.