[英]NSInputStream:read:maxLength: on a TCP socket stream returns the error “The operation couldn’t be completed. Bad file descriptor”
我試圖用OS X上的Objective-C Xcode創建一個簡單的TCP服務器。
似乎連接已被接受,並且我正在獲取應該通過事件處理獲得的所有事件,但是當我嘗試從事件內部的輸入流中讀取時,說有可讀取的數據,我收到以下錯誤消息:
錯誤域= NSPOSIXErrorDomain代碼= 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”事件,但是從流中讀取失敗。 讀取失敗后,輸入流將發送“發生錯誤”事件。
我不知道問題到底出在哪里。 我正在嘗試通過網絡瀏覽器連接。 這是我編寫的代碼:
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
似乎我正在將錯誤的數據傳遞給'CFStreamCreatePairWithSocket()函數。
CFStreamCreatePairWithSocket(kCFAllocatorDefault, *(CFSocketNativeHandle *)data, &rs, &ws);
請注意,我忘記了投射*(CFSocketNativeHandle *)data
,只是發送了(CFSocketNativeHandle)data
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.