Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
412 views
in Technique[技术] by (71.8m points)

objective c - How to use NSOutputStream's write message?

I want to send a UIImage to a server through a socket.

a)I open the outputstream:


- (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) I write NSData to outputstream after open completed and handle the error if error occurs.


- (void) stream: (NSStream *) stream handleEvent: (NSStreamEvent) eventCode
{
    //printf("EVENT: Start.
");

    switch(eventCode)
    {
            case NSStreamEventOpenCompleted:
            {
                //printf("EVENT: Open completed.
");

                if(stream == oStream)
                    {
                        //printf("Sending...
");
                        NSData *data = UIImageJPEGRepresentation(drawImage.image, 90);
                        NSInteger x = [oStream write:[data bytes] maxLength:[data length]];
                    }

                break;
            }
            case NSStreamEventEndEncountered:
            {
                //printf("EVENT: End encountered.
");
                break;
            }
            case NSStreamEventHasSpaceAvailable:
            {
                //printf("EVENT: Has space available.
");
                break;
            }
            case NSStreamEventHasBytesAvailable:
            {
                //printf("EVENT: Has bytes available.
");
                break;
            }
            case NSStreamEventErrorOccurred:
            {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error Occurred"       
                                                                message:nil 
                                                               delegate:nil             
                                                      cancelButtonTitle:@"OK"               
                                                      otherButtonTitles:nil];                   
                [alert show];
                [alert release];
                break;
            }
            case NSStreamEventNone:
            {
                //printf("EVENT: None.
");
                break;
            }
    }

    //printf("EVENT: End.
");
}

When I run this code, NSStreamEventOpenCompleted and NSStreamEventErrorOccurred is called.The NSOutputStream's write method was called successfully and all the data is not nil. But after the data is written to the oStream, the eventCode will change to NSStreamEventErrorOccurred.

So I think maybe it's not the correct way to use [oStream write]. What's the correct way to use this message then? I find this message returns an NSInteger of -1073748088, what might be the problem?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You should be writing the data only after space becomes available in the output stream. When the stream finishes opening, it doesn't always immediately have space available, so writing to it won't work. If you move the write call to the NSStreamEventHasSpaceAvailable handler, it should succeed.

Also, the computer on the other end of the socket has no way of knowing the length of the data you're sending. Unless you're signaling the end-of-data by closing the socket, you should explicitly send the data length along with the data:

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]);
        // Don't forget to check the return value of 'write'
        [oStream write:(uint8_t *)&length maxLength:4];
        [oStream write:[data bytes] maxLength:length];
    }
    break;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...