Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/101.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSOutputStream始终写入零字节_Ios_Nsstream_Cfnetwork - Fatal编程技术网

Ios NSOutputStream始终写入零字节

Ios NSOutputStream始终写入零字节,ios,nsstream,cfnetwork,Ios,Nsstream,Cfnetwork,下面就是苹果公司的文档:-我无法让任何网络NSOutputStream写入数据。它总是返回一个苹果的文档似乎说不应该返回的数字(0-苹果声称这是用于固定大小的流,而不是网络流??) 苹果所有的示例代码都忽略了返回代码(似乎假设它是正数——我在网上发现的很多示例都使用unsigned type!这是非常错误的:()) 我成功地: CFSocketCreate(),带有kCFSocketAcceptCallBack和指向my handleConnect函数的指针 CFSocketSetAddress

下面就是苹果公司的文档:-我无法让任何网络NSOutputStream写入数据。它总是返回一个苹果的文档似乎说不应该返回的数字(0-苹果声称这是用于固定大小的流,而不是网络流??)

苹果所有的示例代码都忽略了返回代码(似乎假设它是正数——我在网上发现的很多示例都使用unsigned type!这是非常错误的:())

我成功地:

  • CFSocketCreate(),带有kCFSocketAcceptCallBack和指向my handleConnect函数的指针
  • CFSocketSetAddress(),带有“any”和手动选择的端口
  • CFRunLoopAddSource()开始侦听端口
  • …所有这些都可以工作,通过远程登录到IP地址+端口进行确认


    …但是,只要遵循苹果的文档,就会出现可怕的错误:

    void handleConnect (
                     CFSocketRef s,
                     CFSocketCallBackType callbackType,
                     CFDataRef address,
                     const void *data,
                     void *info
                     )
    {
        NSLog(@"handleConnect called with callbackType = %li", callbackType);
    
        (myclass) server = (myclass*) info;
    
        BOOL canAccept = callbackType & kCFSocketAcceptCallBack;
        BOOL canWrite = callbackType & kCFSocketWriteCallBack;
        BOOL canRead = callbackType & kCFSocketReadCallBack;
        NSLog(@" ... acceptable? %@  .. readable? %@ .. writeable? %@", canAccept?@"yes":@"no", canRead?@"yes":@"no", canWrite?@"yes":@"no" );
    
        if( canAccept)
        {
            NSLog(@"[%@] Accepted a socket connection from remote host. Address = %@", [server class], addressString );
            /**
             "which means that a new connection has been accepted. In this case, the data parameter of the callback is a pointer to a CFSocketNativeHandle value (an integer socket number) representing the socket.
    
             To handle the new incoming connections, you can use the CFStream, NSStream, or CFSocket APIs. The stream-based APIs are strongly recommended."
             */
    
            // "1. Create read and write streams for the socket with the CFStreamCreatePairWithSocket function."
            CFReadStreamRef clientInput = NULL;
            CFWriteStreamRef clientOutput = NULL;
    
            // for an AcceptCallBack, the data parameter is a pointer to a CFSocketNativeHandle
            CFSocketNativeHandle nativeSocketHandle = *(CFSocketNativeHandle *)data;
    
            CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &clientInput, &clientOutput);
    
            // "2. Cast the streams to an NSInputStream object and an NSOutputStream object if you are working in Cocoa."
    
            // "3. Use the streams as described in “Writing a TCP-Based Client.”
            self.outputBuffer = [NSMutableData dataWithData:[@"Hello" dataWithEncoding:NSUTF8StringEncoding]];
            self.outputBytesWrittenRecently = 0;
            ((NSOutputStream*)output).delegate = self;
    
            [((NSOutputStream*)output) scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [((NSOutputStream*)output) open]; // MUST go last, undocumented Apple bug
        }
    }
    
    …以及委托方法:

    -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
    {
        BOOL streamOpened = eventCode & NSStreamEventOpenCompleted;
        BOOL streamReadyToWrite = eventCode & NSStreamEventHasSpaceAvailable;
        BOOL streamReadyToRead = eventCode & NSStreamEventHasBytesAvailable;
        BOOL streamEnded = eventCode & NSStreamEventEndEncountered;
        BOOL streamErrored = eventCode & NSStreamEventErrorOccurred;
    
        if( streamReadyToWrite )
    #define C_BUFFER_IN_MEMORY_SIZE_WRITE ( 4096 ) // Apple vaguely recommends 4k, but I tried numbers down to 100 with no effect
        uint8_t extraCBufferNSStreamSucks[ C_BUFFER_IN_MEMORY_SIZE_WRITE ];
        NSRange rangeOfBytesToAttemptToWriteNext = { self.outputBytesWrittenRecently, MIN( C_BUFFER_IN_MEMORY_SIZE_WRITE, self.outputBuffer.length - self.outputBytesWrittenRecently) };
        [self.outputBuffer getBytes:&extraCBufferNSStreamSucks range:rangeOfBytesToAttemptToWriteNext];
    
        NSLog(@"About to write data to stream, this might block...");
        NSInteger amountWritten = [self.outputS write:extraCBufferNSStreamSucks maxLength:C_BUFFER_IN_MEMORY_SIZE_WRITE];
        NSLog(@"...finished write data to stream, it might have blocked");
        if( amountWritten > 0 )
        {
            self.outputBytesWrittenRecently += amountWritten;
    
            NSRange totalWrittenRange = { 0, self.outputBytesWrittenRecently };
            NSLog(@"Written %i bytes: %@", amountWritten, [[[NSString alloc] initWithData:[self.outputBuffer subdataWithRange:totalWrittenRange] encoding:NSUTF8StringEncoding] autorelease] );
    
            if( self.outputBytesWrittenRecently == self.outputBuffer.length )
            {
                NSLog(@"Finished writing data!");
    
            }
        }
        else
            NSLog(@"ERROR: failed to write bytes to stream (bytes written = %i)", amountWritten);
    }
    

    啊!未记录,但是…如果您的NSStream实例变为零,而不是返回一个错误,苹果将返回success,但写入的字节数将返回0

    在我的例子中,init方法中的一个输入错误意味着我正在用nil覆盖新捕获的NSOutputStream和NSInputStream


    ARGH.

    你的问题是什么?为什么它返回0?有什么问题?缺少什么?为什么API不能像广告中那样工作?我犯了什么错误?我不知道是什么导致了所描述的行为-我只是遵循了苹果的文档-所以我不能更准确地说:(我看到了你的旗帜。我认为这是值得保留的,只是因为没有记录的NSStream问题。同意-我的错误导致了这一点,这是愚蠢的,但根本的问题(苹果糟糕记录的返回代码0)是有效的。而且…由于这个问题,现在谷歌对苹果API的行为进行了攻击/:)。作为记录,在objective-c中,向nil发送消息是完全可以的,它不会起任何作用。因此,如果您的
    self.outputS
    为nil,则不会返回错误。不会执行任何操作。关于返回0,IMO,这看起来不像是未记录的事情。@nacho4d是的,您关于“发送到nil”的说法是正确的。这是令人困惑的,因为您引用的文档说“如果写入流时出错,返回-1。”-但事实并非如此。这些文档是根据我期望的底层C API编写的,对于Objective-C API来说效果不太好。@nacho4d如果“长度固定且已达到其容量”,则这些文档会说为零。由于网络流根据定义不是固定长度…因此您不希望该方法返回零。