簡體   English   中英

NSInputStream:read:maxLength:在TCP套接字流上返回錯誤“操作無法完成。 錯誤的文件描述符”

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM