I'm programming a client on the iPhone. I want to send some strings, and receive an image from the server.
I found this tutorial (http://www.devx.com/wireless/Article/43551), it has been very useful. It works if I want to receive strings, but now I want to receive an image, and I can't make it work.
This is my code when the iPhone receives data. It's a mix made with the tutorial and this answer from 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;
}}
It doesn't work... could you help me?
Well, I made it work this way, but I'm no sure if there's a better way.
With this method, the received image must be smaller than max_size. If you know a better way to do this, please let me know! ;)
If all you want to do is download an image from the server to display, take a look at this:
https://github.com/michaelkamprath/iPhoneMK/tree/master/Views/MKNetworkImageView
There are a lot of built in functions to the iOS that will handle image downloading for you. That is, if you can encapsulate the entities you want to download as separate URLs (e.g., a web server).
If, however, you are trying to send and receive data across the same TCP connection, I would strongly advise that you change to a more RESTful approach. Partly because it is easier to implement from the client side, partly because you don't have to worry (as much) about the underlying TCP connection.