CFSocket 在成功连接时崩溃
CFSocket crashes on successful connection
这是我用于 CFSocket
通信的客户端和服务器代码,但在成功连接时此代码崩溃。
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
}
在上面的代码中,当 CFSocketConnectToAddress
在客户端中执行时服务器崩溃,之后客户端应用程序也崩溃。
处理 CFSockets 将使您进入处理 POSIX 基础和东西的世界。如果你正在寻找一个简单的 echo/chat 服务器,你应该首先去 NSStream。这要容易得多。这是一个例子:
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)HOST, PORT, &readStream, &writeStream);
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (NSOutputStream *)CFBridgingRelease(writeStream);
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
并像这样处理输入:
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(@"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
if (theStream == inputStream) {
uint8_t buffer[100240];
NSInteger len;
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if (nil != output) {
NSLog(@"Server Response: %@", output);
[self stream:theStream didRecieveResponse:output];
}
}
}
}
break;
case NSStreamEventErrorOccurred:
[self requestDidFailWithResults:@"Can not connect to the host!" andError:theStream.streamError];
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
theStream = nil;
break;
case NSStreamEventEndEncountered:
[self requestDidFailWithResults:@"Request ended" andError:theStream.streamError];
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
theStream = nil;
break;
case NSStreamEventHasSpaceAvailable:
NSLog(@"OutStream is ready");
break;
default:
[self requestDidFailWithResults:@"Unknown event" andError:theStream.streamError];
}
}
_socket = CFSocketCreate (kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)kCFSocketAcceptCallBack, NULL);
在上面的方法中,我必须传递我的回调方法而不是“(CFSocketCallBack)kCFSocketAcceptCallBack”。这解决了我的问题。
这是我用于 CFSocket
通信的客户端和服务器代码,但在成功连接时此代码崩溃。
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
}
在上面的代码中,当 CFSocketConnectToAddress
在客户端中执行时服务器崩溃,之后客户端应用程序也崩溃。
处理 CFSockets 将使您进入处理 POSIX 基础和东西的世界。如果你正在寻找一个简单的 echo/chat 服务器,你应该首先去 NSStream。这要容易得多。这是一个例子:
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)HOST, PORT, &readStream, &writeStream);
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (NSOutputStream *)CFBridgingRelease(writeStream);
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
并像这样处理输入:
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(@"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
if (theStream == inputStream) {
uint8_t buffer[100240];
NSInteger len;
while ([inputStream hasBytesAvailable]) {
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if (nil != output) {
NSLog(@"Server Response: %@", output);
[self stream:theStream didRecieveResponse:output];
}
}
}
}
break;
case NSStreamEventErrorOccurred:
[self requestDidFailWithResults:@"Can not connect to the host!" andError:theStream.streamError];
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
theStream = nil;
break;
case NSStreamEventEndEncountered:
[self requestDidFailWithResults:@"Request ended" andError:theStream.streamError];
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
theStream = nil;
break;
case NSStreamEventHasSpaceAvailable:
NSLog(@"OutStream is ready");
break;
default:
[self requestDidFailWithResults:@"Unknown event" andError:theStream.streamError];
}
}
_socket = CFSocketCreate (kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)kCFSocketAcceptCallBack, NULL);
在上面的方法中,我必须传递我的回调方法而不是“(CFSocketCallBack)kCFSocketAcceptCallBack”。这解决了我的问题。