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

I am trying to wrap my head around making a simple TCP server in Xcode, Objective-C on OS X. 我试图用OS X上的Objective-C Xcode创建一个简单的TCP服务器。

It seems like the connection is accepted, and I am getting all the events that I am supposed to get through the event handling, but when I try to read from the input stream inside the event that says that there are data available to be read, I get the following error message: 似乎连接已被接受,并且我正在获取应该通过事件处理获得的所有事件,但是当我尝试从事件内部的输入流中读取时,说有可读取的数据,我收到以下错误消息:

Error Domain=NSPOSIXErrorDomain Code=9 "The operation couldn't be completed. Bad file descriptor" 错误域= NSPOSIXErrorDomain代码= 9“无法完成操作。错误的文件描述符”

My full debug log is: 我完整的调试日志是:

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"

You can see that both input and output streams sends the "Open Complete" event, then the input stream sends the "Has Bytes Available" event, but reading from the stream fails. 您可以看到输入流和输出流都发送“ Open Complete”事件,然后输入流发送“ Has Bytes Available”事件,但是从流中读取失败。 After reading fails, the input stream sends an "Error Occured" event. 读取失败后,输入流将发送“发生错误”事件。

I am out of ideas what the problem really is. 我不知道问题到底出在哪里。 I am trying to connect with a web browser by the way. 我正在尝试通过网络浏览器连接。 Here is the code I have written: 这是我编写的代码:

The web server: 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

When someone connects: 当有人连接时:

#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

Seems I was passing the wrong data to the 'CFStreamCreatePairWithSocket() function. 似乎我正在将错误的数据传递给'CFStreamCreatePairWithSocket()函数。

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

Notice that I forgot to cast *(CFSocketNativeHandle *)data , just sending (CFSocketNativeHandle)data . 请注意,我忘记了投射*(CFSocketNativeHandle *)data ,只是发送了(CFSocketNativeHandle)data

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 该操作无法完成。 可可错误4 - The operation couldn’t be completed. Cocoa Error 4 该操作无法完成。 没有这样的文件或目录:但是文件存在 - The operation couldn’t be completed. No such file or directory: but the file exists MidiClientCreate“操作无法完成。 (OSStatus错误-50。)” - MidiClientCreate “The operation couldn't be completed. (OSStatus error -50.)” 该操作无法完成。 (可可错误:3840。) - The Operation couldn't be completed. (Cocoa error: 3840.) “这项行动无法完成。 (可可错误512.)“ - “The operation couldn’t be completed. (Cocoa error 512.)” ITLibrary:无法完成操作。 (OSStatus 错误 7011。) - ITLibrary: The operation couldn’t be completed. (OSStatus error 7011.) 该操作无法完成。 (可可错误1560.) - The operation couldn’t be completed. (Cocoa error 1560.) XCode 4 存档/IPA 错误:“操作无法完成。 没有这样的文件或目录” - XCode 4 Archive/IPA Error: “The operation couldn’t be completed. No such file or directory” 如何解决运行时错误&#39;无法创建带有消息的可写数据库文件&#39;无法完成操作。 (可可错误260.)&#39;。&#39;? - how to solve run time error 'Failed to create writable database file with message 'The operation couldn’t be completed. (Cocoa error 260.)'.'? “该操作无法完成。 仅将图像发送到icloud时,“不允许操作”错误 - “The operation couldn’t be completed. Operation not permitted” error when simply sending image to icloud
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM