I was testing a HTTP servlet implementation (kindly shared by BalusC) which supports HTTP byte range requests.
I have found some peculiar differences between differe
You need to send a Accept Ranges header when streaming on iPhone. This may be causing your problem. Look at this post
MP4 plays when accessed directly, but not when read through PHP, on iOS
First of all,
spending loads of time just calculating stack traces
is not going to calculate if you are not gonna call get/printStackTrace(). turn it off the log or catch it and avoid it somewhere.
I had the same problems, it didn't go away for me either. Well, those are really stupid choices to make but you can use a load balancer which is accepting connections and redirecting it your server tomcat or glassfish whatever you are using. i observed this lack of broken-pipe behavior when i started to use ELB on AWS. NGINX or Apache could do some frontier communication for you.
I am saying this because even the operating system could be the reason why JVM doesn't receive proper TCP communication shutdown because of the JVM implementation on the OS.
Coming back on our shared finding. Take a look at this discussion on the apple website. It seems that now this issue has been causing problems with iOS6 consuming too much data while streaming.
(In Dutch language but exactly the same issue reported here. Android doing 1 request, iOS doing multiple requests)
Time to re-test this stuff with iOS6.0.1 to see if they indeed FIXED the range request problems.
Just tested on my iPod Touch 5th Gen - iOS6.0.1: The range request is still requesting 0-1, then a few times 0-full file followed by smaller ranges. However it still looks messy
IIRC, "broken pipe" simply means the other side received data after it closed its read end.
The most reasonable thing I can think of is that it's an attempt to not waste large amounts of bandwidth downloading video that never gets watched (perhaps something they've agreed with carriers, which I suspect is the reasoning behind the "live streaming" restriction:
"Video streaming content over a cellular network longer than 10 minutes must use HTTP Live Streaming and include a baseline 64 kbps audio-only HTTP Live stream."
The only other easy way to throttle the download is to stop read()
ing and wait for the receive window to fill up, but that's not always easy to do (NSURLConnection
really doesn't make this easy, for example).
If you're exceptionally lucky, the client will close its write end (such that the server will read()
EOF) and wait for a little while before closing its read end. In this case, it might be safe to assume that the client no longer wants the rest of the download. RFC 2616 is a little hazy (it seems to forget that sockets can be closed in only one direction) but mentions "graceful close" (which according to Microsoft involves closing the write side and finishing reading from the read side until a timeout passes), but also says
Servers SHOULD NOT close a connection in the middle of transmitting a response, unless a network or client failure is suspected.
So if you know it's an iDevice and you read EOF, then it might be safe for the server to close the socket, provided you've thoroughly tested that it doesn't break anything — changing HTTP behaviour depending on User-Agent just seems like a terrible idea.
Alternatively, don't care. You can do U-A sniffing and ignore the exception if it's an iDevice (which seems less terrible than changing HTTP behaviour). The exception overhead is almost certainly negligible, and probably far lower than the overhead of printing it to a log. 100 exceptions a second is nothing. Profile it if you're unsure.
You could also file a bug with Apple, but as these things go, it's not particularly dubious network behaviour.