I'm working on an iPhone application which will use long-polling to send event notifications from the server to the client over HTTP. After opening a connection on the server I'm sending small bits of JSON that represent events, as they occur. I am finding that -[NSURLConnectionDelegate connection:didReceiveData] is not being called until after I close the connection, regardless of the cache settings I use when creating the NSURLRequest. I've verified that the server end is working as expected - the first JSON event will be sent immediately, and subsequent events will be sent over the wire as they occur. Is there a way to use NSURLConnection to receive these events as they occur, or will I need to instead drop down to the CFSocket API?
I'm starting to work on integrating CocoaAsyncSocket, but would prefer to continue using NSURLConnection if possible as it fits much better with the rest of my REST/JSON-based web service structure.
NSURLConnection will buffer the data while it is downloading and give it all back to you in one chunk with the didReceiveData method. The NSURLConnection class can't tell the difference between network lag and an intentional split in the data.
You would either need to use a lower-level network API like CFSocket as you mention (you would have access to each byte as it comes in from the network interface, and could distinguish the two parts of your payload), or you could take a look at a library like CURL and see what types of output buffering/non-buffering there is there.
I ran into this today. I wrote my own class to handle this, which mimics the basic functionality of NSURLConnection.
http://github.com/nall/SZUtilities/blob/master/SZURLConnection.h
It sounds as if you need to flush the socket on the server-side, although it's really difficult to say for sure. If you can't easily change the server to do that, then it may help to sniff the network connection to see when stuff is actually getting sent from the server.
You can use a tool like Wireshark to sniff your network.
Another option for seeing what's getting sent/received to/from the phone is described in the following article:
http://blog.jerodsanto.net/2009/06/sniff-your-iphones-network-traffic/
Good luck!
We're currently doing some R&D to port our StreamLink comet libraries to the iPhone.
I have found that in the emulator you will start to get didReceiveData callbacks once 1KB of data is received. So you can send a junk 1KB block to start getting callbacks. It seems that on the device, however, this doesn't happen. In safari (on device) you need to send 2KB, but using NSURLConnection I too am getting no callbacks. Looks like I may have to take the same approach.
I might also play with multipart-replace and some other more novel headers and mime types to see if it helps stimulate NSURLConnection.
There is another HTTP API Implementation named ASIHttpRequest. It doesn't have the problem stated above and provides a complete toolkit for almost every HTTP feature, including File Uploads, Cookies, Authentication, ...
http://allseeing-i.com/ASIHTTPRequest/
Related
I am building an OSX app that needs to get data from server. The easy way, is to make a GET request at some fixed time interval, and process results. Thats not what I want. I want the other way around: e.g. server to send data to my app, when something happens on the server side. That way I do not need to make constant requests from client side. I don't need the data to visually be displayed, just processed.
Can this be implemented in OSX with Swift?
You have two ways to achieve this:
Websocket:
Websocket is a full-duplex communication channel over a TCP-Connection. It's established via HTTP.
Long Polling:
Same as you said before but without responding directly. Your client makes a HTTP request and set a very long timeout timer. The server responds after something is happening. (More)
I would recommend you Websocket since it was built exactly for this use case. But if you have to implement it quickly you should probably go with long polling for now, since the barrier to implement it is much lower and switch to Websocket later.
I am trying to develope chat app. I have done created my web service with php and mysql.
The respond of web service is json format.
In swift part; i post some paramaters to web address and retrieve json respond then show the messages. I used use nstimer to post and retrieve the respond of my json respond. And if there is new message the show it.
I dont want to use nstimer for retrieve the message. Is there any better way to do that?
Thank you
If you have a REST-ful service, periodically polling is pretty much the standard way to do it.
Instead of polling, you could consider using a real-time update mechanism to either deliver the message, or else inform your client that you need to sync with the server. Google has developed a pretty robust, cross-platform solution that allows you to achieve this using the Push Notification protocol:
Google GCM XMPP
Take a look at this tutorial. It uses XMPP to pass messages back and forward.
But if you want to do it yourself just to learn you have two options:
Use a restful api where you GET and POST. The timer you have isn't bad. I would recommend changing the time when the app is in the background or not doing it at all. You can use something like parse to send PUSH notifications and reinitiate the GET calls when the user relaunches the app.
You could use WebSockets. WebSockets work a lot like BSD sockets except that they are wrapped in a HTTP(S) tunnel. With web sockets, you can check to see if the client you are looking for is connected. If they are, you just send them the message. If they are not, you do something like in option one using parse to send them a notification.
Hope that helps.
Edit:
Since parse is shutting down, you can use another service like it. I've never used kinvey but it seems that they also provide similar services as parse like the push notification mentioned above
I had been using CFHttp and NSUrlConnection. These classes create a new connection every time to do a http send and receive.
Basically i need a single connection to perform all my send and receive.
Open connection -> send http request -> receive http response ->send http request -> receive http response-> Close connection.
Is there any way to do this.
NSUrlConnection will automagically keep open and re-use a connection for you, via the HTTP 1.1 protocol. (See this accepted answer). It should do this out of the box, unless you're doing something to modify its default behaviour.
I recommend using a network sniffer to verify that connection re-use is happening (or not), and to verify after what amount of time the connection might be dropped (and hence re-opened on next request). Wireshark is a superb network analyzer with good protocol support.
You could also use a third party library; AFNetworking is nice, well designed, and gets good press. (I used to use ASIHttpRequest but it's recently been retired from active development, and its code structure is more monolithic.)
Our web service has a "ping" function which is great for testing if the web service is available or not (I don't really care if the internet connection is available, right?) and I know how to test this condition, but how do I go about implementing this in my application? As in where do I test?
If there is no connection, the app doesn't crash of course, it just returns an empty table view or set of views. Should I put the ping before each request and generate an exception or error message when the ping fails? The web service request + response itself can take longer than the transmission of the actual data (latency I guess it would be) so I worry that implementing a Ping before each request might almost double the time it takes to perform each request. Or, should I be continually ping-ing and making sure there is a connection? What is the best practice?
Or should I even worry about it at all?
I was able to use the Reachability library as seen in the answer to How to check for an active Internet connection on iOS or OSX? . You can extend the library to include not only hostReachable but wsReachable with a little bit of work that is probably obvious to all.
iOS can provide you with callbacks once the network connectivity changes (e.g. from airplane mode to cell only to wifi and back). So you get notified whenever the network state changes and you don't need to keep pinging the server and can display proper online/offline messages.
Have a look at the SCNetworkReachabilitySetCallback method in the NetworkReachability.h header.
I unsuccessfully searched Google for a good definition and understanding of streaming data and its characteristics. My questions are:
What is streaming data?
How can it be detected?
Correction:
"How can it be detected" is not an appropriate question. Instead my question is:
How is it different from buffered data and other data transfer mechanisms?
It depends in what context you mean but basically streaming data is analagous to asynchronous data. Take the Web as an example. The Web (or HTTP specifically) is (basically) a request-response mechanism in that a client makes a request and receives a response (typically a Web page of some kind).
HTTP doesn't natively support the ability for servers to push content to clients. There are a number of ways this can be faked, including:
Polling: forcing the client to make repeated requests, typically inconspicuously (as far as the client is concerned);
Long-lived connections: this is where the client makes a normal HTTP request but instead of returning immediately the server hangs on to the request until there's something to send back. When the request times out or a response is sent th eclient sends another request. In this way you can fake server push;
Plug-ins: Java applets, Flash, Silverlight and others can be used to achieve this.
Anything where the server effectively sends data to the client (rather than the client asking for it)--regardless of the mechanism and whether or not the client is polling for that data--can be characterised as streaming data.
With non-HTTP transports (eg vanilla TCP) server push is typically easier (but can still run afoul of firewalls and th elike). An example of this might be a sharetrading application that receives market information from a provider. That's streaming data.
How do you detect it? Bit of a vague question. I'm not really sure what you're getting at.
When you say streaming data I think of the following, although I'm not sure if this is what you're getting at. To me it's playing a video/audio file while it's downloading. That's what happens when you go to YouTube and watch a video and it starts playing even though you haven't downloaded the whole video yet. But you can see the video downloading - I'm sure you're familiar with the seek bar filling up as the file downloads. It doesn't necessarily have to be a video or audio file but that's the most common.