繁体   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