我正试图在Xcode中创建一个简单的TCP服务器,OS X上的Objective-C。
似乎连接已被接受,并且我正在获取我应该通过事件处理获得的所有事件,但是当我尝试从事件中的输入流中读取时,表明有可用的数据阅读,我收到以下错误信息:
错误Domain = NSPOSIXErrorDomain Code = 9“操作无法完成。错误的文件描述符”
我的完整调试日志是:
handleConnect: ACCEPT
<< Open Complete
>> Open Complete
<< Has Bytes Available
Error Reading Stream
Error Domain=NSPOSIXErrorDomain Code=9 "The operation couldn’t be completed. Bad file descriptor"
Length: 0
<< Error Occured
Error Domain=NSPOSIXErrorDomain Code=9 "The operation couldn’t be completed. Bad file descriptor"
您可以看到输入和输出流都发送“Open Complete”事件,然后输入流发送“Has Bytes Available”事件,但是从流中读取失败。读取失败后,输入流将发送“Error Occured”事件。
我不知道问题究竟是什么。我想尝试连接Web浏览器。这是我写的代码:
网络服务器:
#import "WebServer.h"
@implementation WebServer
- (id)init {
self = [super init];
if (self != nil) {
connections = nil;
}
return self;
}
- (void)start {
CFSocketRef myipv4cfsock = CFSocketCreate(
kCFAllocatorDefault,
PF_INET,
SOCK_STREAM,
IPPROTO_TCP,
kCFSocketAcceptCallBack, handleConnect, NULL);
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(8080);
sin.sin_addr.s_addr= INADDR_ANY;
CFDataRef sincfd = CFDataCreate(
kCFAllocatorDefault,
(UInt8 *)&sin,
sizeof(sin));
CFSocketSetAddress(myipv4cfsock, sincfd);
CFRelease(sincfd);
CFRunLoopSourceRef socketsource = CFSocketCreateRunLoopSource(
kCFAllocatorDefault,
myipv4cfsock,
0);
CFRunLoopAddSource(
CFRunLoopGetCurrent(),
socketsource,
kCFRunLoopDefaultMode);
}
void handleConnect(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) {
if (callbackType == kCFSocketAcceptCallBack) {
printf("handleConnect: ACCEPT\n");
if (connections == nil) {
connections = [[NSMutableArray alloc] init];
}
CFReadStreamRef rs = NULL;
CFWriteStreamRef ws = NULL;
CFStreamCreatePairWithSocket(kCFAllocatorDefault, (CFSocketNativeHandle)data, &rs, &ws);
WebServerConnection *connection = [[WebServerConnection alloc] initWithInputStream:(__bridge NSInputStream *)rs outputStream:(__bridge NSOutputStream *)ws];
[connections addObject:connection];
return;
}
else {
printf("handleConnect: UNKNOWN\n");
}
}
@end
当有人连接时:
#import "WebServerConnection.h"
@implementation WebServerConnection
- (id)init {
self = [super init];
if (self != nil) {
nativeSocket = 0;
readStream = nil;
writeStream = nil;
}
return self;
}
- (id)initWithInputStream:(NSInputStream *)is outputStream:(NSOutputStream *)os {
self = [self init];
if (self != nil) {
readStream = is;
writeStream = os;
[readStream setDelegate:self];
[writeStream setDelegate:self];
[readStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[writeStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[readStream open];
[writeStream open];
data = nil;
}
return self;
}
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
NSString *io = @"??";
if (aStream == readStream) {
io = @"<<";
}
else if (aStream == writeStream) {
io = @">>";
}
switch (eventCode) {
case NSStreamEventOpenCompleted:
printf("%s ", [io UTF8String]);
printf("Open Complete\n");
break;
case NSStreamEventHasBytesAvailable:
{
printf("%s ", [io UTF8String]);
printf("Has Bytes Available\n");
if (data == nil) {
data = [[NSMutableData alloc] init];
}
uint8_t buffer[1024];
NSInteger actuallyRead = [readStream read:(uint8_t *)buffer maxLength:sizeof(buffer)];
if (actuallyRead > 0) {
[data appendBytes:buffer length:actuallyRead];
}
else {
if (actuallyRead == 0) {
printf("End of Data\n");
}
else {
printf("Error Reading Stream\n");
NSError *error = [readStream streamError];
printf("%s\n", [[error description] UTF8String]);
}
}
printf("Length: %lu\n", [data length]);
break;
}
case NSStreamEventHasSpaceAvailable:
printf("%s ", [io UTF8String]);
printf("Has Space Available\n");
break;
case NSStreamEventEndEncountered:
printf("%s ", [io UTF8String]);
printf("End Encountered\n");
break;
case NSStreamEventErrorOccurred:
{
printf("%s ", [io UTF8String]);
printf("Error Occured\n");
NSError *error = [aStream streamError];
printf("%s\n", [[error description] UTF8String]);
[readStream setDelegate:nil];
[writeStream setDelegate:nil];
[readStream close];
[writeStream close];
[readStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[writeStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
break;
}
case NSStreamEventNone:
{
printf("%s ", [io UTF8String]);
printf("None\n");
break;
}
default:
printf("%s ", [io UTF8String]);
printf("Default Clause\n");
break;
}
}
@end
答案 0 :(得分:1)
似乎我将错误的数据传递给&#;; CFStreamCreatePairWithSocket()函数。
CFStreamCreatePairWithSocket(kCFAllocatorDefault, *(CFSocketNativeHandle *)data, &rs, &ws);
请注意,我忘了投放*(CFSocketNativeHandle *)data
,只是发送(CFSocketNativeHandle)data
。