FROM : Jens Alfke
DATE : Sun May 18 20:10:45 2008
On 18 May '08, at 8:50 AM, John MacMullin wrote:
> I modified slightly the Echo Server code sample from Apple with the
> following results. One, I couldn't stream a large file from a
> polling routine. More than likely it would cancel because of a
> Sigterm 15.
Whenever you report a crash, a backtrace is very helpful. Or at least
tell us what function/method the crash was in. This shouldn't crash,
so the problem is probably in something in your code.
> It appears from reading the docs that the user cannot detect the end
> of a stream and that the NSStreamEventEndEncountered only detects a
> close.
"End of stream" and "close" are the same thing: a TCP input stream
ends when the other side closes the connection (or crashes...)
> Two, when unarchiving a file in a client input stream delegate
> method, if the stream terminated from the server because it was too
> large, the client terminates on an unarchiver error because it
> didn't get the whole stream.
A stream won't ever terminate due to length. You can send gigabyte
after gigabyte over a TCP stream, as many happy BitTorrent users can
attest ;-)
But yes, if the incoming stream closed before sending all the data the
reader needed, then I would expect the reader to report an error. This
shouldn't cause a crash, though; it sounds like your code isn't
handling the error gracefully.
> Third, the output stream methods shown in Echo Server are polling
> methods, not delegate methods.
The CocoaEcho sample? I just looked at it, and you're right. The
writing code is badly designed. The client will block in a 'while'
loop until all the data is sent, and the server code will simply drop
response data on the floor if there isn't room to send it. I just
filed feedback on the web page for the sample.
> 1. How do I stream a large file between connections or is NSStream
> the wrong tool? Can the stream size be modified?
Most of the CocoaEcho code is reasonable as a base for doing this. Rip
out the server-side code that echoes the data back, and instead write
the data to a file.
On the client/sender side, it's best to use the 'spaceAvailable'
delegate call, as you said. In response to that call, read some data
from the file into a buffer, then write it to the stream. Something
like 4k will do. Pay attention to the return value of the write, which
tells you how many bytes actually got written, and advance a file-
position instance variable by that amount. That'll tell you the
position to read from in the input file next time.
> 2. What is the largest stream size?
There isn't one. TCP was designed to handle arbitrary length streams.
There are internal byte counters but they just wrap around harmlessly
after 4GB.
> 3. Is it possible to detect a valid archive before I unarchive it,
> or do I simply have to intercept the exception?
No. If you have data in archive format, you have to just hand it to
NSUnarchiver and wrap the call in @try/@catch.
But you said you were sending a file? In that case you should just
send it as a stream of bytes. If you're reading the entire file into
an NSData and then sending that with NSArchiver, that's a huge amount
of overhead for no gain.
> 4. How does one trigger and make available a file an output stream
> so that the delegate methods can be used?
I don't understand that question. Can you give more detail? (Or
perhaps I answered it above under #1.)
—Jens
DATE : Sun May 18 20:10:45 2008
On 18 May '08, at 8:50 AM, John MacMullin wrote:
> I modified slightly the Echo Server code sample from Apple with the
> following results. One, I couldn't stream a large file from a
> polling routine. More than likely it would cancel because of a
> Sigterm 15.
Whenever you report a crash, a backtrace is very helpful. Or at least
tell us what function/method the crash was in. This shouldn't crash,
so the problem is probably in something in your code.
> It appears from reading the docs that the user cannot detect the end
> of a stream and that the NSStreamEventEndEncountered only detects a
> close.
"End of stream" and "close" are the same thing: a TCP input stream
ends when the other side closes the connection (or crashes...)
> Two, when unarchiving a file in a client input stream delegate
> method, if the stream terminated from the server because it was too
> large, the client terminates on an unarchiver error because it
> didn't get the whole stream.
A stream won't ever terminate due to length. You can send gigabyte
after gigabyte over a TCP stream, as many happy BitTorrent users can
attest ;-)
But yes, if the incoming stream closed before sending all the data the
reader needed, then I would expect the reader to report an error. This
shouldn't cause a crash, though; it sounds like your code isn't
handling the error gracefully.
> Third, the output stream methods shown in Echo Server are polling
> methods, not delegate methods.
The CocoaEcho sample? I just looked at it, and you're right. The
writing code is badly designed. The client will block in a 'while'
loop until all the data is sent, and the server code will simply drop
response data on the floor if there isn't room to send it. I just
filed feedback on the web page for the sample.
> 1. How do I stream a large file between connections or is NSStream
> the wrong tool? Can the stream size be modified?
Most of the CocoaEcho code is reasonable as a base for doing this. Rip
out the server-side code that echoes the data back, and instead write
the data to a file.
On the client/sender side, it's best to use the 'spaceAvailable'
delegate call, as you said. In response to that call, read some data
from the file into a buffer, then write it to the stream. Something
like 4k will do. Pay attention to the return value of the write, which
tells you how many bytes actually got written, and advance a file-
position instance variable by that amount. That'll tell you the
position to read from in the input file next time.
> 2. What is the largest stream size?
There isn't one. TCP was designed to handle arbitrary length streams.
There are internal byte counters but they just wrap around harmlessly
after 4GB.
> 3. Is it possible to detect a valid archive before I unarchive it,
> or do I simply have to intercept the exception?
No. If you have data in archive format, you have to just hand it to
NSUnarchiver and wrap the call in @try/@catch.
But you said you were sending a file? In that case you should just
send it as a stream of bytes. If you're reading the entire file into
an NSData and then sending that with NSArchiver, that's a huge amount
of overhead for no gain.
> 4. How does one trigger and make available a file an output stream
> so that the delegate methods can be used?
I don't understand that question. Can you give more detail? (Or
perhaps I answered it above under #1.)
—Jens
| Related mails | Author | Date |
|---|---|---|
| John MacMullin | May 18, 17:50 | |
| Jens Alfke | May 18, 20:10 | |
| Ken Thomases | May 18, 20:26 | |
| John MacMullin | May 19, 06:19 | |
| Jens Alfke | May 19, 08:45 | |
| John MacMullin | May 20, 03:07 | |
| Michael Vannorsdel | May 20, 03:27 | |
| Ken Thomases | May 20, 03:32 | |
| John MacMullin | May 20, 05:26 |






Cocoa mail archive

