RunLoop/CFSocket sample code for RAEL apps (LONG, pt2)
RunLoop/CFSocket sample code for RAEL apps (LONG, pt2)
- Subject: RunLoop/CFSocket sample code for RAEL apps (LONG, pt2)
- From: Jeffrey Johnson <email@hidden>
- Date: Fri, 8 Feb 2002 13:14:49 -0500
// Continued from pt 1
// Apparently, we need to do a two-step dance to use a CFSocket:
// - Setup the socket first as a "rendevous" socket with a
kCFSocketAcceptCallBack callback
// - When the accept callback fires, create a new CFSocket with the
original "native" (BSD)
// socket with a kCFSocketDataCallBack callback to actually receive the data.
// - When the data callback fires, the data sent across the socket
will be in dataPtr
// (a CFDataRef).
//
// In this example, each connection is a "one-shot" -i.e. the client
connects, sends some
// data, optionally gets data back, then closes the socket. Because
of this, the server
// does a CFInvalidate and CFRelease of the (data) CFSocket created
in the accept callback. Another
// connection attempt by a client to this port number will tickle the
accept callback,
// creating another data CFSocket, ad infinitum.
//
static void FESocketAcceptCallBack (CFSocketRef sock,
CFSocketCallBackType type,
CFDataRef theAddr,
const void * dataPtr,
void * info)
{
#pragma unused (sock, theAddr, type, info)
CFSocketRef newSock;
CFRunLoopSourceRef sourceRef;
if ((newSock = CFSocketCreateWithNative(kCFAllocatorDefault,
*(CFSocketNativeHandle *) dataPtr,
kCFSocketDataCallBack,
FESocketDataCallBack,
NULL)) != 0) {
sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault,
newSock,
0);
// same Carbon warning applies as above
CFRunLoopAddSource((CFRunLoopRef)GetCFRunLoopFromEventLoop(GetMainEventLoop()),
sourceRef,
kCFRunLoopDefaultMode);
CFRelease(sourceRef);
}
}
static void FESocketDataCallBack (CFSocketRef sock,
CFSocketCallBackType type,
CFDataRef theAddr,
const void * dataPtr,
void * info)
{
#pragma unused (theAddr, type, info)
CFIndex dataSize;
if ((dataSize = CFDataGetLength((CFDataRef)dataPtr)) > 0) {
// handle your data here. This example prints to stderr.
char *someBuf;
char stringOut[] = "%SUCCESS\n";
CFDataRef dataOut;
if ((someBuf = malloc(dataSize+1)) != nil) {
BlockMoveData(CFDataGetBytePtr((CFDataRef)dataPtr),someBuf,dataSize);
someBuf[dataSize] = '\0';
fprintf(stderr,"SocketUtils: socket received:\n|%s|\n",someBuf);
free(someBuf);
}
// we'll also send a response
if ((dataOut = CFDataCreate(kCFAllocatorDefault,
(const UInt8 *) stringOut,
strlen(stringOut))) != nil) {
CFSocketSendData(sock,NULL,dataOut,0);
CFRelease(dataOut);
};
}
CFSocketInvalidate(sock);
CFRelease(sock);
}
/***************
* sockClient.c *
***************/
// Test client program.
// Shamelessly adapted Jeffrey Johnson 02/08/02 to be self contained
// from a W. Richard Stevens Unix Network Programming example.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#define MAXLINE 16384 /* max #bytes to request from server */
static ssize_t readn(int fd, void *vptr, size_t n);
int
main(int argc, char **argv)
{
int fd;
ssize_t n;
char request[MAXLINE], reply[MAXLINE];
struct sockaddr_in servaddr;
if (argc != 2) {
printf("usage: sockClient <port> ");
exit(1);
}
if ((fd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
printf("socket error");
exit(2);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5555);
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
printf("connect error");
// type some stuff, followed by a <CR>
if ( (n = read(STDIN_FILENO, request, MAXLINE)) == 0)
return(1); // connection closed by other end
write(fd, request, n);
n = readn(fd, reply, MAXLINE);
reply[n] = '\0';
printf("client received:\n%s\n", reply);
close(fd); /* TIME_WAIT on client, not server */
return(0);
}
static ssize_t /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0; /* and call read() again */
else
return(-1);
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return(n - nleft); /* return >= 0 */
}
/* end readn */
--
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.