views:

5177

answers:

9

I'm looking to establish some kind of socket/COMET type functionality from my server(s) to my iPhone application. Essentially, anytime a user manages to set an arbitrary object 'dirty' on the server, by say, updating their Address.. the feedback should be pushed from the server to any clients keeping a live poll to the server. The buzzword for this is COMET I suppose. I know there is DWR out there for web browser applications, so I'm thinking, maybe it's best to set a hidden UIWebView in each of my controllers just so I can get out of the box COMET from their javascript framework? Is there a more elegant approach?

+5  A: 

There are a couple of solutions available to use a STOMP client.

STOMP is incredibly simple and lightweight, perfect for the iPhone.

I used this one as my starting point, and found it very good. It has a few object allocation/memory leak problems, but once I got the hang of iPhone programming, these were easy to iron out.

Hope that helps!

adam
+2  A: 

I wrote a web server for doing exactly this kind of thing. I'm pushing realtime updates through the server with long polling and, as an example, I had safari on the iPhone displaying that data.

A given instance of the server should be able to handle a few thousand concurrent clients without trying too hard. I've got a plan to put them in a hierarchy to allow for more horizontal scaling (should be quite trivial, but doesn't affect my current application).

Dustin
+1  A: 

Would long-polling work for what you want to achieve? You can implement the client-side in a few lines of regular Javascript, which will be lighter than any framework could possibly be.

It would also be trivial to implement it in ObjC (connect, wait for a response or timeout, repeat)

The answers to my question Simple "Long Polling" example code? hopefully explain how extremely simple Long Polling is..

Basically you would just request a URL as usual - the web-server would accept the connection, but not send any data until it's available. When you receive data, or the connection times-out, you reconnect (and repeat)

The most complicated bit would be server server-side, as you cannot use a regular threaded web-server like Apache, although this is also the case with Comet..

dbr
A: 

Do you want/have do the communication for your app over http? If not, you can use CFNetwork framework to use sockets (TCP/UDP) to allow your app and server to communicate. From what I have seen of the CFNetwork stack, it is pretty cool, and makes it fairly straitforward to read and write to streams, and allows for synchronous and asynchronous communication. It also allows for you to define callbacks on your socket allowing you to get notified of events like data received, connection made, etc. So, in your example you could send the information over the socket to your server, and then you could define a callback that would listen for incoming data on the stream and then update your app accordingly.

EDIT: Did a little more research, and if you go the socket approach, you may want to also look at the NSStream classes. They are Cocoa abstractions build on top of the CFSocket stuff.

nstehr
Using raw sockets will be easier (and will definitely perform better), but won't be supported on some carriers. Be sure to offer a Comet or standard HTTP poll fallback
rpetrich
good call on the carrier support, never thought of that initially...
nstehr
+2  A: 

Can you use ordinary TCP/IP socket in your application?

A) If yes then definitely a raw TCP/IP socket is more elegant solution. From your iPhone app you just wait for notification events. The socket is open as long as your application is open. If you want you can even use HTTP protocol / headers.

On the server side you can use some framework to write servers which efficiently handle thousands of open TCP/IP connections. e.g Twisted, EventMachine or libevent. Then just bind the server main socket to http port (80).

The idea is to use a server which keeps just a single data structure per client. Receives update event from some DB application and then pushes it to right client.

B) No, you have to use Apache and http client on iPhone side. Then you should know that whole COMET solution is in fact work around for limitations of HTTP protocol and Apache / PHP.

Apache was designed to handle many short time connections. As far I know only newest versions Apache (mpm worker) can handle efficiently big number of opened connection. Previously Apache was keeping one process per connection.

Web browsers have a limit of concurrent open connections to one web server (URL address in fact, eg. www.foo.com, not IP address of www.foo.com). And the limit is 2 connections. Additionally, a browser will allow only for AJAX connections to the same server from which the main HTML page was downloaded.

Greg Dan
A: 

you didn't mention what serverside tech you're using. But in case it's microsoft .net (or for any other googlers who come across this), there is a simple option for comet: http://www.codeplex.com/ncomet.

Joel Martinez
A: 

COMET, LightStreamer, AJAX all that junk is broken. It is basics of TCP that no 'keep-alives' are ever guaranteed without pinging traffic.. So you can forget that long-polling if any decent reliability or timely delivery is to be guaranteed..

It's just hype everyone saw through back in 2003 when the lame-mania kicked off..

rama-jka toti
If need be you can always send a heartbeat as part of the response. For a javascript response you can send void(); every so often until you have real data to send. Comet is a good solution in situations where HTTP is mandatory (ie. web apps, foreign cell networks that are HTTP-only, etc)
rpetrich
Point is it is no longer a long-running poll, plus you need another TCP connection, plus maintain on server...
rama-jka toti
So JavaScript has to send and keep sending. Making it anything longer than 10 seconds and you know the UI experience will suck. Now start scaling that. And even with persistent connections, when it goes bad it really goes bad like all hacks on hacks..
rama-jka toti
Both Facebook Chat and the Google Talk client inside Gmail are able to do this without problems (both have scaled fine)You would only need to send a heartbeat every ~250seconds or so (TCP limitation, not HTTP)HTTP 1.1 would allow the connection to be reused for multiple requests.
rpetrich
Saying your Gmail is always responsive? Ah, well known issue even internally. 250 seconds is huge, for timely delivery you often go for pings of 5 seconds, and if something requires 2x resources it pretty much tells you everything. Broken. TCP has no limitation ~1sec, it is an app-specific choice.
rama-jka toti
Google and Facebook can afford to scale with cheap servers, AJAX.NET and friends won't do it easy... You were probably aiming at Nagle and often seen especially early ASP.NET and IIS 200 ms issue.. Anyway, mute point, all a hack instead of a RPC-less, reliable, stream client.
rama-jka toti
+1  A: 

WebSync has a javascript client that works on the iPhone, if that's what you're after

jvenema
+1  A: 

StreamHub Comet Server works with the iPhone out of the box, no plugins or anything required. Just browsed to their website on my iPhone and all the examples worked, didn't need to install Flash or anything.

Jeff Atwood