2012-02-25 39 views
4

我正在iPhone上編程客戶端。我想發送一些字符串,並從服務器接收圖像。在iPhone上接收圖像(TCP客戶端)

我發現本教程(http://www.devx.com/wireless/Article/43551),它一直非常有用。它可以工作,如果我想接收字符串,但現在我想收到一個圖像,我不能讓它工作。

這是我的代碼,當iPhone收到數據。這是本教程和JeremyP(http://stackoverflow.com/questions/4613218)這個回答讓混合:

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode { 

switch(eventCode) { 
    case NSStreamEventHasBytesAvailable: { 
     if (data == nil) { 
      data = [[NSMutableData alloc] init]; 
     } 
     uint8_t buf[102400]; 
     unsigned int len = 0; 
     len = [(NSInputStream *)stream read:buf maxLength:102400]; 

     if(len) {  
      [data appendBytes:(const void *)buf length:len]; 

      // Recibir img 
    uint8_t size; // Let's make sure size is an explicit width. 

      NSInteger totalBytesRead = 0; 
      NSInteger bytesRead = [iStream read: &size maxLength: sizeof size]; 
      while (bytesRead > 0 && totalBytesRead + bytesRead < sizeof size) { 
       totalBytesRead+= bytesRead; 
       bytesRead = [iStream read: &size + totalBytesRead maxLength: (sizeof size) - totalBytesRead]; 
      } 
      if (bytesRead >= 0) { 
       totalBytesRead += bytesRead; 
      } 
      else { 
       // read failure, report error and bail 
      } 
      if (totalBytesRead < sizeof size) { 
       // connection closed before we got the whole size, report and bail 
      } 
      size = ntohl(size); // assume wire protocol uses network byte ordering 

      NSMutableData* buffer = [[NSMutableData alloc] initWithLength: size]; 
      totalBytesRead = 0; 
      bytesRead = [iStream read: [buffer mutableBytes] maxLength: size]; 
      while (bytesRead > 0 && totalBytesRead + bytesRead < size) { 
       totalBytesRead+= bytesRead; 
       bytesRead = [iStream read: [buffer mutableBytes] + totalBytesRead maxLength: size - totalBytesRead]; 
      } 
      if (bytesRead >= 0) { 
       totalBytesRead += bytesRead; 
      } 
      else { 
       // read failure, report error and bail (not forgetting to release buffer) 
      } 
      if (totalBytesRead < size) { 
       // connection closed before we got the whole image, report and bail (not forgetting to release buffer) 
      } 
      else { 
       [buffer setLength: size]; 
      } 

      imgResultado.image = [UIImage imageWithData: buffer]; 
      [buffer release]; 
      [data release];   
      data = nil; 

     } 
     else { 
      NSLog(@"No data."); 
     } 


    } break; 
}} 

它不工作...你能幫助我嗎?

回答

3

嗯,我是這樣做的,但我不確定是否有更好的方法。

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode { 
switch(eventCode) { 
    case NSStreamEventHasBytesAvailable: 
    { 
     uint32_t max_size = 1000000; // Max size of the received imaged. 
     NSMutableData* buffer = [[NSMutableData alloc] initWithLength: max_size]; 
     NSInteger totalBytesRead = 0; 
     NSInteger bytesRead = [(NSInputStream *)stream read: [buffer mutableBytes] maxLength: max_size]; 
     if (bytesRead != 0) { 
      while (bytesRead > 0 && totalBytesRead + bytesRead < max_size) { 
       totalBytesRead+= bytesRead; 
       bytesRead = [(NSInputStream *)stream read: [buffer mutableBytes] + totalBytesRead maxLength: max_size - totalBytesRead]; 
      } 
      if (bytesRead >= 0) { 
       totalBytesRead += bytesRead; 
      } 
      else { 
       // read failure, report error and bail (not forgetting to release buffer) 
      } 
      [buffer setLength: totalBytesRead]; 
      imgResultado.image = [UIImage imageWithData: buffer]; 
      [buffer release]; 
     } 
    } break; 
}} 

使用這種方法,接收到的圖像必須小於max_size。 如果你知道更好的方法來做到這一點,請讓我知道! ;)

+0

這意味着您的服務器不像您之前的代碼所期望的那樣在流的開始處傳輸大小整數。這就是爲什麼你以前的代碼不起作用,因爲如果圖像數據有效地丟棄了前4個字節。 – kamprath 2012-02-27 02:19:47

+0

因此,使用此代碼,您可以接收高達1000000字節的圖像。這差不多是1MB? (您的原始代碼只有大約100k?)只要嘗試確認... – user523234 2012-02-27 04:05:27

+1

user523234是的,客戶端可以接收圖像高達1000000字節。 Claireware,這可能是一個很好的解釋,我認爲你是對的。這種方式比我的答案更安全,但如果我想使用它,我需要修改服務器。 – Xithias 2012-02-27 08:40:32

0

如果你想要做的是從服務器上顯示下載圖像,看看這個:

https://github.com/michaelkamprath/iPhoneMK/tree/master/Views/MKNetworkImageView

有很多的內置功能來將處理圖像的iOS爲你下載。也就是說,如果您可以將要下載的實體封裝爲單獨的URL(例如,Web服務器)。

但是,如果您嘗試通過相同的TCP連接發送和接收數據,我強烈建議您更改爲更加REST風格的方法。部分原因是從客戶端實現更容易,部分原因是您不必擔心底層TCP連接(儘可能多)。

+0

該圖像不在網絡中。服務器使用客戶端發送的數據生成圖像,然後通過TCP連接發送圖像。我必須在iPhone中編程TCP客戶端才能接收並顯示該圖像。 – Xithias 2012-02-26 04:20:05

+0

你知道服務器返回的數據格式嗎? imageWithData:僅適用於JPG,PNG等。如果您的服務器正在返回原始像素數據,那麼這將不起作用。 – kamprath 2012-02-26 06:26:44

+0

收到的圖像是JPG。 – Xithias 2012-02-26 15:19:30