Re: Datagram Socket Reading?
Re: Datagram Socket Reading?
- Subject: Re: Datagram Socket Reading?
- From: Douglas Davidson <email@hidden>
- Date: Fri, 17 May 2002 13:42:39 -0700
On Thursday, May 16, 2002, at 06:55 PM, Douglas Davidson wrote:
No, you don't need that extra thread. You can use CFSocket for this.
CFSocket is a CF type intended to allow sockets of more or less
arbitrary type to serve as run loop sources. Note that CFSocket is not
intended as a complete wrapper around the BSD sockets APIs; you still
deal with a socket as usual, but you can be notified in your run loop
e.g. when data arrives. There was a session at the recent WWDC that
discussed this, among other issues. I'll see if I can put together
some sample code for the UDP case.
There's another apple mailing list, email@hidden,
where we've been discussing CFSocket. I posted to that list a small
sample that I had presented at the recent WWDC session, showing
minimally the use of CFSocket with TCP sockets. That's fairly easily
adaptable to UDP.
Douglas Davidson
Here's the original sample. This gives a trivial http response to any
request. The example is a bit abbreviated so as to fit on the slides,
but it shows some of the basic ideas. Compiles with cc -framework
CoreFoundation.
#import <CoreFoundation/CoreFoundation.h>
#include <sys/socket.h>
#include <netinet/in.h>
void receiveData(CFSocketRef child, CFSocketCallBackType type, CFDataRef
address, const void *data, void *info) {
static char helloWorld[] = "HTTP/1.0 200 OK\r\n\r\nhello, world\r\n";
CFDataRef response = CFDataCreate(NULL, helloWorld,
strlen(helloWorld));
CFSocketSendData(child, NULL, response, 0.0);
CFRelease(response);
CFSocketInvalidate(child);
CFRelease(child);
}
void acceptConnection(CFSocketRef socket, CFSocketCallBackType type,
CFDataRef address, const void *data, void *info) {
CFSocketRef child = CFSocketCreateWithNative(NULL,
*(CFSocketNativeHandle *)data, kCFSocketDataCallBack, receiveData, NULL);
CFRunLoopSourceRef childSource = CFSocketCreateRunLoopSource(NULL,
child, 0);
CFRunLoopRef loop = CFRunLoopGetCurrent();
CFRunLoopAddSource(loop, childSource, kCFRunLoopDefaultMode);
CFRelease(childSource);
}
int main (int argc, const char *argv[]) {
struct sockaddr_in a = {0, AF_INET, 1234, 0};
CFDataRef d = CFDataCreate(NULL, (UInt8 *)&a, sizeof(struct
sockaddr_in));
CFSocketSignature signature = {PF_INET, SOCK_STREAM, IPPROTO_TCP, d};
CFSocketRef socket = CFSocketCreateWithSocketSignature(NULL,
&signature, kCFSocketAcceptCallBack, acceptConnection, NULL);
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(NULL,
socket, 0);
CFRunLoopRef loop = CFRunLoopGetCurrent();
CFRunLoopAddSource(loop, source, kCFRunLoopDefaultMode);
CFRunLoopRun();
}
Here's a UDP example, this time an echo server:
#import <CoreFoundation/CoreFoundation.h>
#include <sys/socket.h>
#include <netinet/in.h>
void receiveData(CFSocketRef socket, CFSocketCallBackType type,
CFDataRef address, const void *data, void *info) {
CFSocketSendData(socket, address, (CFDataRef)data, 0.0);
}
int main (int argc, const char *argv[]) {
struct sockaddr_in a = {0, AF_INET, 1234, 0};
CFDataRef d1 = CFDataCreate(NULL, (UInt8 *)&a, sizeof(struct
sockaddr_in));
CFSocketSignature signature = {PF_INET, SOCK_DGRAM, IPPROTO_UDP, d};
CFSocketRef socket = CFSocketCreateWithSocketSignature(NULL,
&signature, kCFSocketDataCallBack, receiveData, NULL);
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(NULL,
socket, 0);
CFRunLoopRef loop = CFRunLoopGetCurrent();
CFRunLoopAddSource(loop, source, kCFRunLoopDefaultMode);
CFRunLoopRun();
}
Now, these two examples both use kCFSocketDataCallBack; this causes
CFSocket to not only notify you of data coming in, but also to read the
data and present it to you. This makes for compact examples, but there
are a number of situations where you will want to use
kCFSocketReadCallBack instead, which causes CFSocket simply to notify
you when data is available, and expect you to do the read yourself.
These examples also use CFSocketSendData(), which is a small convenience
API for writing, which again is useful for producing compact examples.
You may also wish to do the write part yourself; the primary purpose of
CFSocket is simply to provide notifications in the run loop for various
socket events, not to wrap other socket functionality like reading and
writing.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.