Re: Closing CFWriteStreams (re-sent)
Re: Closing CFWriteStreams (re-sent)
- Subject: Re: Closing CFWriteStreams (re-sent)
- From: Eli Bach <email@hidden>
- Date: Thu, 19 Jun 2008 20:23:32 -0700
On Jun 19, 2008, at 7:02 PM, Terry Lambert wrote:
On Jun 19, 2008, at 6:35 PM, Eli Bach wrote:
How can I do an orderly vs a disorder TCP disconnect using
CFWriteStream in my daemon?
If I CFWriteStreamClose() immediately after my last
CFWriteStreamWrite(), the data may or may not get sent out.
From the documentation, I gather that CFWriteStream buffers data
internally before actually sending it down the wire, and I can
query it if I can add data to the buffer, but there doesn't seem to
be a way to query if that write buffer is empty, or to flush the
buffer before closing the stream.
I'm using CFRead/WriteStreams using events on a single runloop.
You do not give enough information about how you got it associated
with the stream in the first place, but typically, you can do a:
CFWriteStreamCopyProperty( stream,
kCFStreamPropertySocketNativeHandle)
and then call shutdown(2) on the fd you get back.
It may also do this automatically in the close, if you set the
socket back to blocking, if you are using it non-blocking.
Typically, a close flushes buffered output before returning.
See also:
<http://developer.apple.com/documentation/Networking/Conceptual/CFNetwork/CFNetwork.pdf
>
which shows up in the first page of google results for
"CFWriteStreamClose socket".
-- Terry
Terry,
First, I resent the message because I didn't receive the first one
from the list [and from way back, I expected to receive it].
Yes, I have poked around in that document [as it also shows up in the
documentation in XCode] searching for info related to CFWriteStream.
For the daemon [the server], I use:
[to listen to the server socket on the runloop]
CFSocketCreate(PF_INET, SOCK_STREAM, IPPROTO_TCP,
kCFSocketAcceptCallBack),
setsockopt(CFSocketGetNative(), SO_REUSEADDR)
CFSocketSetAddress(0.0.0.0:port)
CFSocketCreateRunLoopSource()
CFRunLoopAddSource
Then in the callback that a connection was made, to create and setup
the read/write streams:
CFStreamCreatePairWithSocket()
CFReadStreamSetProperty(kCFStreamPropertyShouldCloseNativeSocket, true)
CFWriteStreamSetProperty(kCFStreamPropertyShouldCloseNativeSocket, true)
CFReadStreamSetClient(kCFStreamEventOpenCompleted bitor
kCFStreamEventHasBytesAvailable
bitor kCFStreamEventCanAcceptBytes bitor kCFStreamEventErrorOccurred
bitor kCFStreamEventEndEncountered)
CFWriteStreamSetClient(kCFStreamEventOpenCompleted bitor
kCFStreamEventHasBytesAvailable
bitor kCFStreamEventCanAcceptBytes bitor kCFStreamEventErrorOccurred
bitor kCFStreamEventEndEncountered)
CFReadStreamScheduleWithRunLoop()
CFWriteStreamScheduleWithRunLoop()
CFReadStreamOpen()
CFWriteStreamOpen()
then I only handle events for these streams from callbacks on the
runloop.
For the client, I use
CFStreamCreatePairWithSocketToHost()
CFReadStreamSetProperty(kCFStreamPropertyShouldCloseNativeSocket,
kCFBooleanTrue
CFWriteStreamSetProperty(kCFStreamPropertyShouldCloseNativeSocket,
kCFBooleanTrue
and the code picks up in the above outline at the same spot [and the
code is shared between client and server].
Right now, it seems that using CFWriteStreamClose(), then releasing
the stream with the above setup doesn't force the data stream to be
flushed.
I'll try switching 'kCFStreamPropertyShouldCloseNativeSocket' to
false, then get the socket and do a close() or shutdown() on the
socket explicitly. Of course, I hate the idea of needing to spin off
another thread just to call close() [as it should block waiting for
all the data to be sent, and would halt the runloop doing it there].
I'll also look around in the CF source that is available, to see how
it might be implemented [as there's no guarantee that Apple actually
uses that exact code on MacOSX].
Or is there another, better way to do this?
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden