• 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
RunLoop/CFSocket sample code for RAEL apps (LONG, pt1)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RunLoop/CFSocket sample code for RAEL apps (LONG, pt1)


  • Subject: RunLoop/CFSocket sample code for RAEL apps (LONG, pt1)
  • From: Jeffrey Johnson <email@hidden>
  • Date: Fri, 8 Feb 2002 13:12:45 -0500

From Douglas Davidson's pthreaded server sample code posted here (macnetworkprog) on 02/04 (and spending a DTS Incident directing me here), I've put together some sample code suitable for a Carbon app using RunApplicationEventLoop(). This code allows a RAEL app to listen to a TCP port and respond using CFRunLoop callbacks (i.e. no threads required).
This code could quickly become Bottleneck City, performancewise - it's really only sufficient for simple, small "request-reply" transactions. If you're writing a server with lots of connections going on, you should use threads/the threaded example previously posted as a base.
But if you have some "backend" Unix program (that shouldn't link to CarbonLib for one reason or another) that needs to initiate a connection to a Carbon UI app (a CarbonLib-less pgm can't *initiate* an AE to a CarbonLib UI app, but can receive and reply to them. Bummer. Like a phone without a dial/keypad), using this code with a high numbered TCP socket might work for you. I've also enclosed a short client program ripped off from Stevens for testing.
Since this whole effort was part of a Ring-like quest for narrative Apple documentation :-), I've probably gotten something wrong- feel free to post corrections/suggestions (but hey, this code compiles- and runs- apparently correctly- and has a few (gasp) comments- some SDK code doesn't :-))))). This is in two parts (together, 12k)...

/****************
* SocketUtils.c *
****************/

// These routines form the skeleton to allow a Carbon UI app to listen
// on a TCP port (as a "server") and process data from "clients" as a
// callback attached to the normal RAEL event/run loop (so you don't
// need to make another thread just to do simple BSD socket I/O). This code
// was written for use on MacOS 10.1 and above, and was tested on a RAEL
// C app.
//
// Adapted by Jeffrey Johnson 02/08/02 from example code posted to
// macnetworkprog-list 02/04/02 by Douglas Davidson.
// All comments/editorial content is mine (JJ) and may be erroneous
// in part or in full.
//
// Posted as a public service, since as of this date (02/02) there is
// *still* no narrative documentation on CFRunLoops, CFSockets, or even
// CFData except what's in the header files or what gets posted/answered
// on the mailing lists (Thanks Douglas), and some of us would like to
// understand so we can ship (and help Apple sell boxes). :-)
// This code has *no* support- I don't work for Apple (at least, not
// when I wrote this :-)). Feel free to contribute fixes/comments to the
// macnetworkprog mailing list.
//
// See sockClient.c for a client program (which uses only BSD calls)
// which can be run out of a Terminal window for testing.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

// Call this somewhere early (OK to call before RAEL)
void MakeTCPServerSocketForCarbonApp(int port, CFSocketRef *boundSocket);
// call this before app quit time (at least)
void ReleaseCarbonAppTCPSocket(CFSocketRef *boundSocket);


static void FESocketDataCallBack (CFSocketRef sock,
CFSocketCallBackType type,
CFDataRef theAddr,
const void * dataPtr,
void * info);

static void FESocketAcceptCallBack (CFSocketRef sock,
CFSocketCallBackType type,
CFDataRef theAddr,
const void * dataPtr,
void * info);

void MakeTCPServerSocketForCarbonApp(int port, CFSocketRef *boundSocket)
{

CFDataRef servRef;
struct sockaddr_in servAddr;
CFSocketSignature sockSig;
CFRunLoopSourceRef sourceRef;
unsigned int yes= 1;

*boundSocket = nil;

bzero(&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(port);
// allows any host to connect, might want to change to loopback for security
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);

// create a CFDataRef of the servAddr for the CFSocketSignature
servRef = CFDataCreate(kCFAllocatorDefault,(UInt8 *)&servAddr,sizeof(servAddr));

sockSig.protocolFamily = AF_INET;
sockSig.socketType = SOCK_STREAM;
sockSig.protocol = 0;
sockSig.address = servRef;

// make a "rendevous socket" that is bound to this TCP port
if ((*boundSocket =
CFSocketCreateWithSocketSignature(kCFAllocatorDefault,
&sockSig,
kCFSocketAcceptCallBack,
FESocketAcceptCallBack,
NULL)) != nil &&
(sourceRef =
CFSocketCreateRunLoopSource(kCFAllocatorDefault,
*boundSocket,
0)) != nil) {


// get the run loop for the main event loop (requires 10.1)
// (warned this might be necessary in future by Carbon engrs)

CFRunLoopAddSource((CFRunLoopRef)GetCFRunLoopFromEventLoop(GetMainEventLoop()),
sourceRef,
kCFRunLoopDefaultMode);

// the sourceRef is retained by the run loop- release our ref
CFRelease(sourceRef);

// As of this writing, I'm not sure why the socket needs
// REUSEADDR/REUSEPORT set
setsockopt(CFSocketGetNative(*boundSocket),
SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes));
setsockopt(CFSocketGetNative(*boundSocket),
SOL_SOCKET,SO_REUSEPORT,&yes,sizeof(yes));
}

CFRelease(servRef);

}

// call this when we're completely done with the port (app is quitting)
void ReleaseCarbonAppTCPSocket(CFSocketRef *boundSocket)
{
if (*boundSocket) {
CFSocketInvalidate(*boundSocket);
CFRelease(*boundSocket);
*boundSocket = nil;
}
}
// End of part 1
--
Thanks
Jeffrey Johnson
Macintosh Development
Wavefunction, Inc.
_______________________________________________
macnetworkprog mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/macnetworkprog
Do not post admin requests to the list. They will be ignored.

  • Follow-Ups:
    • Re: RunLoop/CFSocket sample code for RAEL apps (LONG, pt1)
      • From: Douglas Davidson <email@hidden>
  • Prev by Date: Re: Name resolution limits
  • Next by Date: RunLoop/CFSocket sample code for RAEL apps (LONG, pt2)
  • Previous by thread: Re: Name resolution limits
  • Next by thread: Re: RunLoop/CFSocket sample code for RAEL apps (LONG, pt1)
  • Index(es):
    • Date
    • Thread