Re: Network Programming Models
Re: Network Programming Models
- Subject: Re: Network Programming Models
- From: Douglas Davidson <email@hidden>
- Date: Mon, 4 Feb 2002 13:46:32 -0800
On Monday, February 4, 2002, at 10:18 AM, Chris Silverberg wrote:
As an alternative alternative, if your application is Mac OS X-only
and CFRunLoop based (Carbon or Cocoa are), you can use CFNetwork. It
delivers data to your application from a runloop event source, which
means it runs cooperatively with respect to all the other events in
your application.
I assume you are also (mostly?) referring to CFSocket which would
probably
be more useful to most of us. Speaking of this approach, is there any
sample code available that would show CFRunLoop/CFSocket in action? Or
perhaps forthcoming sample code? :-)
CFNetwork is much richer and more extensive than CFSocket; really the
only thing that CFSocket does is to allow a socket to be used as a run
loop source. However, if that is what you are after (and that may well
be the case) then you may wish to use CFSocket directly.
I don't have any polished sample code, but here's a little throwaway
piece of code I had lying around. This isn't intended to be an example
of anything more than creating CFSockets and adding them to run
loops--multiple run loops, in this case. Keep in mind that there is
precisely one run loop for each thread. If you are running on the main
thread of a Carbon or Cocoa application, you usually don't run that run
loop yourself, because the frameworks run it for you as part of their
main event loop--you just add your sources to the current run loop and
you get callbacks automatically.
Douglas Davidson
#import <CoreFoundation/CoreFoundation.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
static char hello[] = "HTTP/1.0 200 OK\r\nContent-Type:
text/html\r\n\r\n<h1>Hello, everybody!</h1>This is a test.\r\n";
CFDataRef createResponseForRequest(CFDataRef request) {
char buffer[1024];
snprintf(buffer, sizeof(buffer), "%s<br>Response from thread
%p.\r\n", hello, pthread_self());
return CFDataCreate(NULL, buffer, strlen(buffer));
}
void dealWithConnectionSocket(CFSocketRef cs, CFSocketCallBackType type,
CFDataRef address, const void *data, void *info) {
CFDataRef response;
response = createResponseForRequest((CFDataRef)data);
if (response) {
CFSocketSendData(cs, NULL, response, 0);
CFRelease(response);
}
CFSocketInvalidate(cs);
CFRelease(cs);
}
void dealWithRendezvousSocket(CFSocketRef s, CFSocketCallBackType type,
CFDataRef address, const void *data, void *info) {
CFSocketRef cs = CFSocketCreateWithNative(NULL,
*(CFSocketNativeHandle *)data, kCFSocketDataCallBack,
dealWithConnectionSocket, NULL);
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(NULL, cs, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), source,
kCFRunLoopDefaultMode);
CFRelease(source);
}
void *rendezvousSocketManager(void *s) {
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(NULL,
(CFSocketRef)s, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), source,
kCFRunLoopDefaultMode);
CFRelease(source);
CFRunLoopRun();
return (void *)0;
}
int main (int argc, const char *argv[]) {
CFSocketRef s = CFSocketCreate(NULL, PF_INET, SOCK_STREAM,
IPPROTO_TCP, kCFSocketAcceptCallBack, dealWithRendezvousSocket, NULL);
struct sockaddr_in sin;
CFDataRef address;
unsigned int i, yes = 1;
setsockopt(CFSocketGetNative(s), SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(yes));
setsockopt(CFSocketGetNative(s), SOL_SOCKET, SO_REUSEPORT, &yes,
sizeof(yes));
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(1234);
address = CFDataCreate(NULL, (UInt8 *)&sin, sizeof(sin));
CFSocketSetAddress(s, address);
CFRelease(address);
for (i = 0; i < 5; i++) {
pthread_t thread;
pthread_create(&thread, NULL, rendezvousSocketManager, s);
pthread_detach(thread);
}
rendezvousSocketManager(s);
exit(0);
return 0;
}