This is my Client and Server code for CFSocket
communication but on successful connection this code crashes.
Client.m
-(void)createConnection
{
CFSocketContext socketContext = {0,(__bridge void *)(self),NULL,NULL,NULL};
_socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketConnectCallBack,(CFSocketCallBack)kCFSocketConnectCallBack, &socketContext);
if (_socket != nil) {
struct sockaddr_in addr4;
memset (& addr4, 0, sizeof (addr4));
addr4.sin_len = sizeof (addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons (8888);
NSString *strAddress = @"xxx.xxx.x.xxx";
addr4.sin_addr.s_addr = inet_addr ([strAddress UTF8String]);
CFDataRef address = CFDataCreate (kCFAllocatorDefault, (UInt8 *) & addr4, sizeof (addr4));
CFSocketConnectToAddress (_socket,address,-1);
CFSocketEnableCallBacks(_socket, kCFSocketConnectCallBack);
CFRunLoopRef cRunRef = CFRunLoopGetCurrent ();
CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource (kCFAllocatorDefault, _socket, 0);
CFRunLoopAddSource (cRunRef,sourceRef,kCFRunLoopCommonModes);
char ethadd []= "helloworld";
CFDataRef Data = CFDataCreate(NULL, (const UInt8*)ethadd, sizeof(ethadd));
int socket_error = CFSocketSendData (_socket, (CFDataRef) address, (CFDataRef) Data, 10);
if (socket_error < 0){
NSLog(@"Data could not be sent!");
// return EXIT_FAILURE;
}
else NSLog(@"Data Sent");
CFRelease (sourceRef);
}
}
void TCPServerConnectCallBack (CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void * data, void * info) {
if (data != NULL) {
// When the socket is kCFSocketConnectCallBack failure callback failed to return an error code pointer, other returns NULL
NSLog (@"connection failed");
return;
}
Client * client = (__bridge Client *) info;
[client readStream];
}
- (void)readStream {
char buffer [1024];
while (recv (CFSocketGetNative (_socket), // ??Socket associated with the authority has failed to return -1: INVALID_SOCKET is
buffer, sizeof (buffer), 0)) {
NSLog (@"%@", [NSString stringWithUTF8String: buffer]);
}
}
- (void) SendMessage :(NSString *)text {
// [self createConnection];
NSString * stringTosend = text;
char * data = (char *)[stringTosend UTF8String];
send (CFSocketGetNative (_socket), data, strlen (data) + 1, 0);
}
Server.m
-(void)setupSocket
{
setupSocket();
}
int setupSocket () {
_socket = CFSocketCreate (kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)kCFSocketAcceptCallBack, NULL);
if (NULL == _socket) {
NSLog (@ "Cannot create socket!");
return 0;
}
int optval = 1;
setsockopt (CFSocketGetNative (_socket), SOL_SOCKET, SO_REUSEADDR, // ??allow reuse of local address and port
(void *) & optval, sizeof (optval));
struct sockaddr_in addr4;
memset (& addr4, 0, sizeof (addr4));
addr4.sin_len = sizeof (addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons (8888);
addr4.sin_addr.s_addr = inet_addr ([@"xxx.xxx.x.xxx" UTF8String]);//htlon(INADDR_ANY)
CFDataRef address = CFDataCreate (kCFAllocatorDefault, (UInt8 *) & addr4, sizeof (addr4));
if (kCFSocketSuccess != CFSocketSetAddress (_socket, address)) {
NSLog (@ "Bind to address failed!");
if (_socket)
CFRelease (_socket);
_socket = NULL;
return 0;
}
CFSocketEnableCallBacks(_socket, kCFSocketAcceptCallBack);
CFRunLoopRef cfRunLoop = CFRunLoopGetCurrent ();
CFRunLoopSourceRef source = CFSocketCreateRunLoopSource (kCFAllocatorDefault, _socket, 0);
CFRunLoopAddSource (cfRunLoop, source, kCFRunLoopCommonModes);
return 1;
}
void TCPServerAcceptCallBack (CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void * data, void * info) {
if (kCFSocketAcceptCallBack == type) {
// Local socket handle
CFSocketNativeHandle nativeSocketHandle = * (CFSocketNativeHandle *) data;
uint8_t name [SOCK_MAXADDRLEN];
socklen_t nameLen = sizeof (name);
if (0 != getpeername (nativeSocketHandle, (struct sockaddr *) name, & nameLen)) {
NSLog (@"error");
// Exit (1);
}
NSLog (@ "%s connected.", inet_ntoa (((struct sockaddr_in *) name) -> sin_addr));
CFReadStreamRef iStream;
CFWriteStreamRef oStream;
CFReadStreamClientCallBack readStream;
CFReadStreamClientCallBack writeStream;
CFWriteStreamRef wStream;
// Create a socket connection can read and write
CFStreamCreatePairWithSocket (kCFAllocatorDefault, nativeSocketHandle, &iStream, & oStream);
if (iStream && oStream) {
CFStreamClientContext streamContext = {0, NULL, NULL, NULL};
if (! CFReadStreamSetClient (iStream, kCFStreamEventHasBytesAvailable,
readStream, // callback function is called when the data readable
&streamContext)) {
// Exit (1);
}
if (! CFReadStreamSetClient (iStream, kCFStreamEventCanAcceptBytes, writeStream, &streamContext)) {
// Exit (1);
}
CFReadStreamScheduleWithRunLoop (iStream, CFRunLoopGetCurrent (), kCFRunLoopCommonModes);
CFWriteStreamScheduleWithRunLoop (wStream, CFRunLoopGetCurrent (), kCFRunLoopCommonModes);
CFReadStreamOpen (iStream);
CFWriteStreamOpen (wStream);
}
else
{
close (nativeSocketHandle);
}
}
}
// Read data
void readStream (CFReadStreamRef stream, CFStreamEventType eventType, void * clientCallBackInfo) {
UInt8 buff [255];
CFReadStreamRead (stream, buff, 255);
printf ("received:%s", buff);
}
void writeStream (CFWriteStreamRef stream, CFStreamEventType eventType, void * clientCallBackInfo) {
outputStream = stream;
}
//int main()
//{
// char * str = "nihao";
// UInt8 buff [255];
// if (outputStream != NULL) {
// CFWriteStreamWrite (outputStream, buff, strlen (str) + 1);
// }
// else
// {
// NSLog (@ "Cannot send data!");
// }
//}
// Open up a thread in the thread function
void runLoopInThread () {
int res = setupSocket ();
if (res) {
EXIT_FAILURE;
}
CFRunLoopRun (); // run the current thread CFRunLoop of objects
}
In the above code crashes for Server when CFSocketConnectToAddress
executes in Client and after that client app also crashes.
_socket = CFSocketCreate (kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)kCFSocketAcceptCallBack, NULL);
In above method i had to pass my callback method instead of "(CFSocketCallBack)kCFSocketAcceptCallBack".Which fixed my issue.