NSInputStream:read:maxLength: 在 TCP 套接字流上返回错误"The operation couldn’t be completed. Bad file descript



我正在尝试在Xcode中制作一个简单的TCP服务器,OS X上的Objective-C。

似乎连接被接受,并且我正在通过事件处理获得我应该获得的所有事件,但是当我尝试从事件内部的输入流中读取说有数据可供读取时,我收到以下错误消息:

错误域=

NSPOSIXError域代码=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"

您可以看到输入流和输出流都发送"打开完成"事件,然后输入流发送"有可用字节数"事件,但从流读取失败。 读取失败后,输入流发送"发生错误"事件。

我不知道问题到底是什么。 顺便说一下,我正在尝试连接网络浏览器。 这是我编写的代码:

网络服务器:

#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: ACCEPTn");
        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: UNKNOWNn");
    }
}
@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 Completen");
            break;
        case NSStreamEventHasBytesAvailable:
        {
            printf("%s ", [io UTF8String]);
            printf("Has Bytes Availablen");
            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 Datan");
                }
                else {
                    printf("Error Reading Streamn");
                    NSError *error = [readStream streamError];
                    printf("%sn", [[error description] UTF8String]);
                }
            }
            printf("Length: %lun", [data length]);
            break;
        }
        case NSStreamEventHasSpaceAvailable:
            printf("%s ", [io UTF8String]);
            printf("Has Space Availablen");
            break;
        case NSStreamEventEndEncountered:
            printf("%s ", [io UTF8String]);
            printf("End Encounteredn");
            break;
        case NSStreamEventErrorOccurred:
        {
            printf("%s ", [io UTF8String]);
            printf("Error Occuredn");
            NSError *error = [aStream streamError];
            printf("%sn", [[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("Nonen");
            break;
        }
        default:
            printf("%s ", [io UTF8String]);
            printf("Default Clausen");
            break;
    }
}
@end

似乎我把错误的数据传递给了'CFStreamCreatePairWithSocket(( 函数。

    CFStreamCreatePairWithSocket(kCFAllocatorDefault, *(CFSocketNativeHandle *)data, &rs, &ws);

请注意,我忘了投*(CFSocketNativeHandle *)data,只是发送(CFSocketNativeHandle)data

相关内容

最新更新