Re: NSStream, NSInputStream, NSOutputStream
Re: NSStream, NSInputStream, NSOutputStream
- Subject: Re: NSStream, NSInputStream, NSOutputStream
- From: John MacMullin <email@hidden>
- Date: Sun, 18 May 2008 21:19:32 -0700
Jens and Ken:
Thank you for your responses. I believe I now understand in part as
to what is happening as to the streams. Let me take the output
"trigger" first. The Stream Programming Guide states: "if the
delegate receives an NSStreamEventHasSpaceAvailable event and does
not write anything to the stream, it does not receive further space-
available events from the run loop until the NSOutputStream object
receives more bytes." This may answer the question of the
"trigger", which is I now believe is simply the write statement.
That means that instead of doing a polling loop outside of the
delegate, (or doing writes inside the NSStreamEventHasBytesAvailable
section of the delegate during reads) I think that all one needs to
do is to write one byte in the "external" function, then handle the
rest of the writes through the delegate
NSStreamEventHasSpaceAvailable event. That should be a lot easier
than doing a custom polling loop and trying to resolve the space
available issues outside of the delegate. In other words, it seems
that the delegate should do it for you after doing a one byte write.
I'll let you know how it works out. And I will address the other
questions after I have tested this issue.
Best regards,
John
On May 18, 2008, at 11:10 AM, Jens Alfke wrote:
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
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden