• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Closing CFWriteStreams (re-sent)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


  • Follow-Ups:
    • Re: Closing CFWriteStreams (re-sent)
      • From: Terry Lambert <email@hidden>
    • Re: Closing CFWriteStreams (re-sent)
      • From: "Eli Bach" <email@hidden>
References: 
 >Closing CFWriteStreams (re-sent) (From: Eli Bach <email@hidden>)
 >Re: Closing CFWriteStreams (re-sent) (From: Terry Lambert <email@hidden>)

  • Prev by Date: Re: Closing CFWriteStreams (re-sent)
  • Next by Date: Re: Closing CFWriteStreams (re-sent)
  • Previous by thread: Re: Closing CFWriteStreams (re-sent)
  • Next by thread: Re: Closing CFWriteStreams (re-sent)
  • Index(es):
    • Date
    • Thread