Когда закрывать NSOutputStream? - PullRequest
2 голосов
/ 03 апреля 2009

Я хочу отправить данные UIImage на сервер через сокет, поэтому я:

а) открыть 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) записывать данные в oStream при наличии свободного места


- (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;
}

Проблема в том, что данные продолжают записывать в oSream снова и снова. Как остановить это, когда все данные отправлены?

Я отправляю длину данных перед данными изображения, чтобы сервер знал, когда он достигнет конца. Должен ли я изменить код на стороне сервера, чтобы закрыть сокет, когда он достигнет конца? И где я могу добавить [oStream close], чтобы закрыть oStream на стороне клиента?

1 Ответ

5 голосов
/ 03 апреля 2009

Проблема в том, что данные продолжают записывать в oSream снова и снова. Как остановить это, когда все данные отправлены?

Видите, это опасность мышления пассивным голосом. Перепишите вопрос активным голосом:

Проблема в том, что данные продолжают записываться в oSream снова и снова. Как остановить это, когда я отправил все данные?

И вы почти ответили на свой вопрос.

Большая часть проблемы - ваш обработчик HasSpaceAvailable. Вот что вы делаете:

  1. Создание полного представления JPEG изображения (каждый раз)
  2. Отправка длины представления (каждый раз)
  3. Отправка первой части представления (каждый раз)

Это три проблемы, и вам нужно решить все три.

  1. Создайте представление JPEG один раз.
  2. Отправьте длину представления только один раз.
  3. Следите за тем, что вы уже отправили, и отправляйте только первую часть того, чего у вас нет.

Чтобы сделать все три, поместите длину в NSMutableData и добавьте представление JPEG к нему. Затем сохраните этот новый объект данных и получите дополнительные переменные экземпляра для байтового указателя и оставшейся длины. Вы сделаете все это до того, как попадете в состояние HasSpaceAvailable.

Тогда, когда вы доберетесь до HasSpaceAvailable, не отправляйте длину отдельно, потому что вы поместили ее в объект данных. Вам нужно только отправить байты из переменной экземпляра указателя с длиной, оставшейся в качестве максимальной длины. После того, как вы проверите, что количество отправленных байтов не было 0 или -1 (см. документацию ), добавьте его к указателю и вычтите его из оставшейся длины.

Когда оставшаяся длина достигает нуля, вы отправили все. Предполагая, что вы не хотите отслеживать данные JPEG чем-либо, вы можете закрыть поток.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...