NSOutputStream(TCP)无限期挂起:重构代码后写入

时间:2015-01-21 22:30:18

标签: ios objective-c

我有一些用于在TCP NSStream上写/读的代码。我重构了它,现在NSOutputStream:write无限期地挂起了。花了几个小时看着它,不能破解它。我看到TCP SYN-> ACK过程正常 - 我回到旧版本进行测试,它仍然有效(所以另一端的设备很好)。

一切都在一个线程上完成(流创建,委托,读/写等),这不是主线程。线程在重构中根本没有改变。

以下是创建流的代码(重构没有变化):

CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)_cam.IP, PTPIP_PORT, &readStream, &writeStream);
_mainInputStream = (__bridge NSInputStream *)readStream;
_mainOutputStream = (__bridge NSOutputStream *)writeStream;
[_mainInputStream setDelegate:self];
[_mainOutputStream setDelegate:self];

[_mainInputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; // common mode!
[_mainOutputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; // common mode!
[_mainInputStream open];
[_mainOutputStream open];

[[NSRunLoop currentRunLoop] run];

这是在编写时失败的新代码,它在流上挂起:写入。当我在写入调用之前检查流状态时,流是打开的(好)。我之前调试了函数的输入。在重构之后,没有区别(好)。我还想过检查一下流委托NSStreamEventHasSpaceAvailable,但是对于旧的(工作的)或新的(破坏的)代码似乎都不会被抛出,所以我想它不适用于TCP以我使用它们的方式进行流式传输。像NSStreamEventHasBytesAvailable这样的其他流委托事件正好被抛出......

- (int)write:(const unsigned char*)bytes size:(unsigned int)size {

unsigned int bytesToWrite = size;

while( bytesToWrite > 0) {

    unsigned int chunkSize = (bytesToWrite > PTP_IP_MAX_PACKET_LEN)?PTP_IP_MAX_PACKET_LEN:bytesToWrite;

    // welcome to hangsville, population YOU
    int result = [self.myWorker.mainOutputStream write:bytes+(size-bytesToWrite) maxLength:chunkSize];

    if( result <= 0 )
        return PTP_ERROR_IO;
    bytesToWrite -= result;
}

return size-bytesToWrite;
}

这里是以某种方式工作的旧代码,即使输入是相同的......

static short
ptpip_write_func (unsigned char *bytes, unsigned int size, void *data)
{
PTPCamera* cam = (__bridge PTPCamera*)data;

unsigned int bytesToWrite = size;

while( bytesToWrite > 0) {

    unsigned chunkSize = (bytesToWrite > PTP_IP_MAX_PACKET_LEN)?PTP_IP_MAX_PACKET_LEN:bytesToWrite;
    unsigned char chunk[chunkSize];
    memcpy(chunk, bytes+(size-bytesToWrite), chunkSize);

    int result = [cam.outStream write:chunk maxLength:chunkSize];
    if( result <= 0 )
        return PTP_ERROR_IO;
    bytesToWrite -= result;
}

return PTP_RC_OK;
}

我错过了什么?

1 个答案:

答案 0 :(得分:1)

经过大量的调试后,我得出结论,这两个版本之间确实没有什么不同的事情发生,而且它一定是flu that that 工作。

果然,在进行了额外的研究之后,我发现在除了main之外的任何线程上进行流打开调用都无法正常工作。

以下是更新后的代码:

CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)cam.IP, PTPIP_PORT, &readStream, &writeStream);
worker.mainInputStream = (__bridge NSInputStream *)readStream;
worker.mainOutputStream = (__bridge NSOutputStream *)writeStream;
[worker.mainInputStream setDelegate:worker];
[worker.mainOutputStream setDelegate:worker];

dispatch_async(dispatch_get_main_queue(), ^{

    [worker.mainInputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [worker.mainOutputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [worker.mainInputStream open];
    [worker.mainOutputStream open];
});