2009-04-01 4 views
6

Je veux envoyer un UIImage à un serveur via une socket.Comment utiliser le message d'écriture de NSOutputStream?

a) J'ouvre la 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) J'écris NSData à fluxSortie après ouverture terminée et gérer l'erreur en cas d'erreur.


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

Quand je lance ce code, NSStreamEventOpenCompleted et NSStreamEventErrorOccurred est la méthode d'écriture de called.The NSOutputStream a été appelé avec succès et toutes les données ne sont pas nulles. Mais après que les données ont été écrites dans l'oStream, le code d'événement devient NSStreamEventErrorOccurred. Donc, je pense que ce n'est pas la bonne façon d'utiliser [oStream write]. Quelle est la bonne façon d'utiliser ce message alors? Je trouve ce message renvoie un NSInteger de -1073748088, quel pourrait être le problème?

+0

Qu'est-ce que [ostream streamError] vous donner? – Chuck

+0

L'opération n'a pas pu être terminée. Expiration du délai d'expiration –

Répondre

13

Vous ne devez écrire les données qu'une fois l'espace disponible dans le flux de sortie. Lorsque le flux finit d'être ouvert, il ne dispose pas toujours immédiatement d'espace disponible, l'écriture ne fonctionnera donc pas. Si vous déplacez l'appel write vers le gestionnaire NSStreamEventHasSpaceAvailable, il doit réussir.

En outre, l'ordinateur situé à l'autre extrémité de la socket n'a aucun moyen de connaître la longueur des données que vous envoyez. À moins que vous signalant la fin de données en fermant la prise, vous devez envoyer explicitement la longueur des données ainsi que les données:

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; 
} 
+1

Un message d'avertissement s'affiche: Dans [oStream write: & length], length est un type de pointeur incompatible. –

+0

J'ai mis à jour le code - juste cast à un uint8_t * pour se débarrasser de l'avertissement. (Cela viole techniquement les règles strictes d'aliasing du C99, mais en pratique cela n'aura aucune importance.) –

+0

L'oStream continue maintenant d'envoyer la longueur et les données au serveur. Le serveur ne connaît toujours pas la fin des données. Où puis-je ajouter [oStream close] ;? Ou devrais-je ajouter du code au côté serveur pour le fermer? –

Questions connexes