简体   繁体   English

Stream 获取数据 - NSInputStream

[英]Stream to Get Data - NSInputStream

All,全部,

I have a server that has a tcp socket stream for communication.我有一台服务器,它有一个用于通信的 tcp 套接字 stream。 I need to get to that stream and read the initial data that it needs to send me.我需要到达那个 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 并读取它需要发送给我的初始数据。

My current code is as follows.我当前的代码如下。 To be honest, I'm going at this completely blind.老实说,我完全是盲目的。 I'm not sure if this is correct let alone the right thing for the job.我不确定这是否正确,更不用说适合这份工作了。

-(void) initNetworkCommunication
{
    //input stream
    NSInputStream *iStream;
    NSURL *url = [url initWithString:@"192.168.17.1:2004"];

    [iStream initWithURL:url];
    [iStream setDelegate:self];
    [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [iStream open];

}

So from the way I see it, this code initializes the stream, but how do I read from the stream?所以从我看到的方式来看,这段代码初始化了stream,但是我如何从stream中读取呢?

Thanks谢谢

There are two ways to get data from a stream: polling and using stream events.有两种方法可以从 stream 获取数据:轮询和使用 stream 事件。

Polling is simpler, but will block the thread it is running in. If you use this method, you don't need to perform the setDelegate: or scheduleInRunLoop:forMode: calls.轮询更简单,但会阻塞它正在运行的线程。如果使用此方法,则无需执行setDelegate:scheduleInRunLoop:forMode:调用。 Polling is performed by repeatedly calling read:maxLength: .通过重复调用read:maxLength:来执行轮询。

NSInteger result;
uint8_t buffer[BUFFER_LEN]; // BUFFER_LEN can be any positive integer
while((result = [iStream read:buffer maxLength:BUFFER_LEN]) != 0) {
    if(result > 0) {
        // buffer contains result bytes of data to be handled
    } else {
        // The stream had an error. You can get an NSError object using [iStream streamError]
    }
}
// Either the stream ran out of data or there was an error

Using stream events requires setting the delegate and adding the stream to a run loop.使用 stream 事件需要设置委托并将 stream 添加到运行循环。 Instead of blocking the thread, the stream will send a stream:handleEvent: message to its delegate when certain events occur, including when it receives data. stream 不会阻塞线程,而是在某些事件发生时(包括接收数据时)向其委托发送stream:handleEvent:消息。 The delegate can then retrieve the data from the stream.然后,代理可以从 stream 检索数据。 Here is an example stream:handleEvent: method:这是一个示例stream:handleEvent:方法:

- (void)stream:(NSInputStream *)iStream handleEvent:(NSStreamEvent)event {
    BOOL shouldClose = NO;
    switch(event) {
        case  NSStreamEventEndEncountered:
            shouldClose = YES;
            // If all data hasn't been read, fall through to the "has bytes" event
            if(![iStream hasBytesAvailable]) break;
        case NSStreamEventHasBytesAvailable: ; // We need a semicolon here before we can declare local variables
            uint8_t *buffer;
            NSUInteger length;
            BOOL freeBuffer = NO;
            // The stream has data. Try to get its internal buffer instead of creating one
            if(![iStream getBuffer:&buffer length:&length]) {
                // The stream couldn't provide its internal buffer. We have to make one ourselves
                buffer = malloc(BUFFER_LEN * sizeof(uint8_t));
                freeBuffer = YES;
                NSInteger result = [iStream read:buffer maxLength:BUFFER_LEN];
                if(result < 0) {
                    // error copying to buffer
                    break;
                }
                length = result;
            }
            // length bytes of data in buffer
            if(freeBuffer) free(buffer);
            break;
        case NSStreamEventErrorOccurred:
            // some other error
            shouldClose = YES;
            break;
    }
    if(shouldClose) [iStream close];
}

I came up with this, based on some other answers.我想出了这个,基于其他一些答案。

public enum StreamError: Error {
    case Error(error: Error?, partialData: [UInt8])
}

extension InputStream {

    public func readData(bufferSize: Int = 1024) throws -> Data {
        var buffer = [UInt8](repeating: 0, count: bufferSize)
        var data: [UInt8] = []

        open()

        while true {
            let count = read(&buffer, maxLength: buffer.capacity)

            guard count >= 0 else {
                close()
                throw StreamError.Error(error: streamError, partialData: data)
            }

            guard count != 0 else {
                close()
                return Data(bytes: data)
            }

            data.append(contentsOf: (buffer.prefix(count)))
        }

    }
}

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM