Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slow file transfer using Multipeer Connectivity framework

I'm sending a file between two devices using iOS 7's Multipeer Connectivity Framework. I'm using NSStreams to tranfer the file, as my previous attempt using MCSession's sendData:toPeers:withMode was really unreliable. Unfortunately the transfer speeds I'm getting are really slow, around 100kb/s, which won't work for the application I'm working on. Here are my Input and Output stream delegate methods, which is where the file transfer happens.

Output Stream (in the delegate for the stream)

...//previous code
 case NSStreamEventHasSpaceAvailable: {
            //we will only open the stream when we want to send the file.

            NSLog(@"Stream has space available");
            //[self updateStatus:@"Sending"];

            // If we don't have any data buffered, go read the next chunk of data.

            if (totalBytesWritten< outgoingDataBuffer.length) {
                //more stuff to read
                int towrite;
                int diff = outgoingDataBuffer.length-packetSize;
                if (diff <= totalBytesWritten)
                {
                    towrite = outgoingDataBuffer.length - totalBytesWritten;
                } else
                    towrite = packetSize;
                NSRange byteRange = {totalBytesWritten, towrite};
                uint8_t buffer[towrite];
                [outgoingDataBuffer getBytes:buffer range:byteRange];


                NSInteger bytesWritten = [outputStream write:buffer maxLength:towrite];
                totalBytesWritten += bytesWritten;
                NSLog(@"Written %d out of %d bytes",totalBytesWritten, outgoingDataBuffer.length);
            } else {
                //we've written all we can write about the topic?
                NSLog(@"Written %d out of %d bytes",totalBytesWritten, outgoingDataBuffer.length);
                [self endStream];
            }

            // If we're not out of data completely, send the next chunk.
        } break;

Input Stream

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

    switch(eventCode) {
        case NSStreamEventHasBytesAvailable:
        {
            NSLog(@"Bytes Available");
            //Sent when the input stream has bytes to read, we need to read bytes or else this wont be called again
            //when this happens... we want to read as many bytes as we can

            uint8_t buffer[1024];
            int bytesRead;

            bytesRead = [inputStream read:buffer maxLength:sizeof(buffer)];
            [incomingDataBuffer appendBytes:&buffer length:bytesRead];
            totalBytesRead += bytesRead;
            NSLog(@"Read %d bytes, total read bytes: %d",bytesRead, totalBytesRead);

        }break;
        case NSStreamEventEndEncountered:
        {
            UIImage *newImage = [[UIImage alloc]initWithData:incomingDataBuffer];
            [[self.detailViewController imageView] setImage:newImage];
            NSLog(@"End Encountered");

            [self closeStream];
            //this should get called when there aren't any more bytes being sent down the stream
        }
    }
 }

Is there a way to speed up this file transfer through either multithreading or using a slightly modified NSStream subclass that makes use of asynchronous sockets?

like image 576
Corey Zambonie Avatar asked Oct 10 '13 21:10

Corey Zambonie


3 Answers

There are a couple of things I have noticed that cause slow file transfers:

  • Having a non-airdrop compatible device in the session (http://en.wikipedia.org/wiki/AirDrop)
  • WiFi issues (saturated network, router problems, the channel, etc.)

I have been getting decent speeds (and by decent I mean 500K / second) between an iPhone 5S, iPad Air and iPhone Simulator on the MAC.

like image 131
jjxtra Avatar answered Nov 03 '22 05:11

jjxtra


I had some pretty decent transfer rates going for a while and suddenly it seemed that I was receiving one packet every 15 to 30 seconds. All looked fine on the sender side, but the packets trickle into the receiver. I use sendData:toPeers:withMode in my app.

One of my devices had WiFi turned off. Turning it back on restored my performance even though neither device is connected to a wifi network.

So I'm only ever doing peer-to-peer ad-hoc connections with MPC, but still, with no WiFi hub involved, it appears that iOS is making use of the WiFi signal to carry my data.) I did see in a presentation from Apple a while back that MPC over straight BlueTooth is a dog and I can tell you for a fact that it is.

like image 31
Dan Loughney Avatar answered Nov 03 '22 05:11

Dan Loughney


MPC work on WiFi or bluetooth so it depends on what you are using. If you are using wifi to send files than you will get maximum speed as per the network strength.

like image 28
Kevin Mac Avatar answered Nov 03 '22 06:11

Kevin Mac