简体   繁体   中英

When to close NSOutputStream?

I want to send the data of a UIImage to the server through a socket, so I:

a) open NSOutputStream


- (IBAction)send:(id)sender {
    NSURL *website = [NSURL URLWithString:str_IP];
    NSHost *host = [NSHost hostWithName:[website host]];
    [NSStream getStreamsToHost:host port:1100 inputStream:nil outputStream:&oStream];
    [oStream retain];
    [oStream setDelegate:self];
    [oStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [oStream open];
}

b) write data to oStream when space is available


- (void) stream: (NSStream *) stream handleEvent: (NSStreamEvent) eventCode
{
switch(eventCode)
    {
    case NSStreamEventHasSpaceAvailable:
    {
            if(stream == oStream)
            {
                    NSData *data = UIImageJPEGRepresentation(drawImage.image, 90);
                    //Convert from host to network endianness
                    uint32_t length = (uint32_t)htonl([data length]);

                    [oStream write:(uint8_t *)&length maxLength:4];
                    [oStream write:[data bytes] maxLength:length];
            }
    }
    break;
}

The problem is that the data keeps writing to the oSream again and again. How to stop it when all the data is sent?

I send the length of the data before the Image data in order to let the server know when it reaches the end. Do I have to change the code in the server side to close the socket when it reaches the end? And where can I add [oStream close] to close the oStream in the client side?

The problem is that the data keeps writing to the oSream again and again. How to stop it when all the data is sent?

See, this is the danger of thinking in the passive voice. Reword the question in the active voice:

The problem is that the data keeps writing to the oSream again and again. How to stop it when I have sent all the data?

And you have almost answered your own question.

A large part of the problem is your HasSpaceAvailable handler. Here's what you're doing:

  1. Creating a complete JPEG representation of the image (every time)
  2. Sending the length of the representation (every time)
  3. Sending the first portion of the representation (every time)

These are three problems and you need to solve all three.

  1. Create the JPEG representation once.
  2. Send the length of the representation only once.
  3. Keep track of what you have already sent and only send the first part of what you haven't.

To do all three, put the length into an NSMutableData and append the JPEG representation to it. Then, retain this new data object, and have additional instance variables for the bytes pointer and the length remaining. You'll do all this before you get to the HasSpaceAvailable state.

Then, when you do get to HasSpaceAvailable , don't separately send the length, because you've put it into the data object. You need only send the bytes from your pointer instance variable with the length remaining as the max length. After you check that the number of bytes sent was not 0 or -1 (see the documentation ), add it to the pointer and subtract it from the length remaining.

When the length remaining reaches zero, you have sent everything. Assuming you don't want to follow the JPEG data up with something, you can then close the stream.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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