一直在努力
分类:
2010-09-08 15:54:56
我们从为一个文件创建可读流开始,列表2-1,所示。
Listing 2-1 Creating a read stream from a file
CFReadStreamRef myReadStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL); |
file:///Users/joeuser/Downloads/MyApp.sit
.isting 2-2 Opening a read stream
if (!CFReadStreamOpen(myReadStream)) { |
CFStreamError myErr = CFReadStreamGetError(myReadStream); |
// An error has occurred. |
if (myErr.domain == kCFStreamErrorDomainPOSIX) { |
// Interpret myErr.error as a UNIX errno. |
} else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) { |
// Interpret myErr.error as a MacOS error code. |
OSStatus macError = (OSStatus)myErr.error; |
// Check other error domains. |
} |
} |
Working with Write Streams
Listing 2-5 Creating, opening, writing to, and releasing a write stream
CFWriteStreamRef myWriteStream = |
CFWriteStreamCreateWithFile(kCFAllocatorDefault, fileURL); |
if (!CFWriteStreamOpen(myWriteStream)) { |
CFStreamError myErr = CFWriteStreamGetError(myWriteStream); |
// An error has occurred. |
if (myErr.domain == kCFStreamErrorDomainPOSIX) { |
// Interpret myErr.error as a UNIX errno. |
} else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) { |
// Interpret myErr.error as a MacOS error code. |
OSStatus macError = (OSStatus)myErr.error; |
// Check other error domains. |
} |
} |
UInt8 buf[] = "Hello, world"; |
UInt32 bufLen = strlen(buf); |
while (!done) { |
CFTypeRef bytesWritten = CFWriteStreamWrite(myWriteStream, buf, strlen(buf)); |
if (bytesWritten < 0) { |
CFStreamError error = CFWriteStreamGetError(myWriteStream); |
reportError(error); |
} else if (bytesWritten == 0) { |
if (CFWriteStreamGetStatus(myWriteStream) == kCFStreamStatusAtEnd) { |
done = TRUE; |
} |
} else if (bytesWritten != strlen(buf)) { |
// Determine how much has been written and adjust the buffer |
bufLen = bufLen - bytesWritten; |
memmove(buf, buf + bytesWritten, bufLen); |
// Figure out what went wrong with the write stream |
CFStreamError error = CFWriteStreamGetError(myWriteStream); |
reportError(error); |
} |
} |
CFWriteStreamClose(myWriteStream); |
CFRelease(myWriteStream); |
myWriteStream = NULL; |
Listing 2-6 Polling a read stream
while (!done) { |
if (CFReadStreamHasBytesAvailable(myReadStream)) { |
UInt8 buf[BUFSIZE]; |
CFIndex bytesRead = CFReadStreamRead(myReadStream, buf, BUFSIZE); |
if (bytesRead < 0) { |
CFStreamError error = CFReadStreamGetError(myReadStream); |
reportError(error); |
} else if (bytesRead == 0) { |
if (CFReadStreamGetStatus(myReadStream) == kCFStreamStatusAtEnd) { |
done = TRUE; |
} |
} else { |
handleBytes(buf, bytesRead); |
} |
} else { |
// ...do something else while you wait... |
} |
} |
Listing 2-7 is a polling example for a write stream.
Listing 2-7 Polling a write stream
UInt8 buf[] = "Hello, world"; |
UInt32 bufLen = strlen(buf); |
while (!done) { |
if (CFWriteStreamCanAcceptBytes(myWriteStream)) { |
int bytesWritten = CFWriteStreamWrite(myWriteStream, buf, strlen(buf)); |
if (bytesWritten < 0) { |
CFStreamError error = CFWriteStreamGetError(myWriteStream); |
reportError(error); |
} else if (bytesWritten == 0) { |
if (CFWriteStreamGetStatus(myWriteStream) == kCFStreamStatusAtEnd) |
{ |
done = TRUE; |
} |
} else if (bytesWritten != strlen(buf)) { |
// Determine how much has been written and adjust the buffer |
bufLen = bufLen - bytesWritten; |
memmove(buf, buf + bytesWritten, bufLen); |
// Figure out what went wrong with the write stream |
CFStreamError error = CFWriteStreamGetError(myWriteStream); |
reportError(error); |
} |
} else { |
// ...do something else while you wait... |
} |
} |
This example begins by creating a socket read stream:
CFStreamCreatePairWithSocketToCFHost(kCFAllocatorDefault, host, port, |
&myReadStream, NULL); |
host
, specifies the remote host with which the read stream is to be made and the port
parameter specifies the port number that the host uses. The CFStreamCreatePairWithSocketToCFHost
function returns the new read stream reference in myReadStream
. The last parameter, NULL
, indicates that the caller does not want to create a write stream. If you wanted to create a write steam, the last parameter would be, for example, &myWriteStream
.efore opening the socket read stream, create a context that will be used when you register to receive stream-related events:
CFStreamClientContext myContext = {0, myPtr, myRetain, myRelease, myCopyDesc}; |
copyDescription
is a parameter to a function to provide a description of the stream. For example, if you were to call CFCopyDesc(myReadStream)
with the stream client context shown above, CFStream would callmyCopyDesc(myPtr)
.The client context also allows you the option of setting the retain
, release
, and copyDescription
parameters toNULL
. If you set the retain
and release
parameters to NULL
, then the system will expect you to keep the memory pointed to by the info
pointer alive until the stream itself is destroyed. If you set the copyDescription
parameter to NULL
, then the system will provide, if requested, a rudimentary description of what is in the memory pointed to by the info
pointer.
With the client context set up, call the function CFReadStreamSetClient
to register to receive stream-related events. CFReadStreamSetClient
requires that you specify the callback function and the events you want to receive. The following example in Listing 2-8 specifies that the callback function wants to receive thekCFStreamEventHasBytesAvailable
, kCFStreamEventErrorOccurred
, and kCFStreamEventEndEncountered
events. Then schedule the stream on a run loop with the CFReadStreamScheduleWithRunLoop
function. SeeListing 2-8 for an example of how to do this.
Listing 2-8 Scheduling a stream on a run loop
CFOptionFlags registeredEvents = kCFStreamEventHasBytesAvailable | |
kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered; |
if (CFReadStreamSetClient(myReadStream, registeredEvents, myCallBack, &myContext) |
{ |
CFReadStreamScheduleWithRunLoop(myReadStream, CFRunLoopGetCurrent(), |
kCFRunLoopCommonModes); |
} |
With the stream scheduled on the run loop, you are ready to open the stream as shown in Listing 2-9.
Listing 2-9 Opening a nonblocking read stream
if (!CFReadStreamOpen(myReadStream)) { |
CFStreamError myErr = CFReadStreamGetError(myReadStream); |
if (myErr.error != 0) { |
// An error has occurred. |
if (myErr.domain == kCFStreamErrorDomainPOSIX) { |
// Interpret myErr.error as a UNIX errno. |
strerror(myErr.error); |
} else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) { |
OSStatus macError = (OSStatus)myErr.error; |
} |
// Check other domains. |
} else |
// start the run loop |
CFRunLoopRun(); |
} |
Now, wait for your callback function to be executed. In your callback function, check the event code and take appropriate action. See Listing 2-10.