Как использовать сообщение для записи NSOutputStream? - PullRequest
6 голосов
/ 01 апреля 2009

Я хочу отправить UIImage на сервер через сокет.

а) Я открываю выходной поток:


- (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) Я записываю NSData в выходной поток после завершения открытия и обрабатываю ошибку, если происходит ошибка.


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

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

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

                break;
            }
            case NSStreamEventEndEncountered:
            {
                //printf("EVENT: End encountered.\n");
                break;
            }
            case NSStreamEventHasSpaceAvailable:
            {
                //printf("EVENT: Has space available.\n");
                break;
            }
            case NSStreamEventHasBytesAvailable:
            {
                //printf("EVENT: Has bytes available.\n");
                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.\n");
                break;
            }
    }

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

Когда я запускаю этот код, вызывается NSStreamEventOpenCompleted и NSStreamEventErrorOccurred. Метод записи NSOutputStream был успешно вызван, и все данные не равны нулю. Но после того, как данные записаны в oStream, eventCode изменится на NSStreamEventErrorOccurred.

Так что я думаю, что, возможно, это неправильный способ использования [oStream write]. Как правильно использовать это сообщение? Я считаю, что это сообщение возвращает NSInteger -1073748088, в чем может быть проблема?

1 Ответ

13 голосов
/ 01 апреля 2009

Вы должны записывать данные только после того, как пространство станет доступным в выходном потоке. Когда поток завершает открытие, у него не всегда есть свободное место, поэтому запись в него не будет работать. Если вы переместите вызов write в обработчик NSStreamEventHasSpaceAvailable, он должен завершиться успешно.

Кроме того, компьютер на другом конце сокета не может узнать длину отправляемых данных. Если вы не сигнализируете об окончании данных, закрывая сокет, вы должны явно отправить длину данных вместе с данными:

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...