2

I'm trying to create an application that has the ability to transfer large files between iOS devices through what I'll call a "true" peer-to-peer network ie two devices connected directly to each other without an intermediate router / wi-fi network. I've determined I have three high level options:

1) Apple's Multipeer Connectivity library, which enables discovery of other nearby devices and also includes the ability to send what Apple coins "Resources" aka files. My prototyping with this revealed this Framework is awful at sending large files (200 MB+). Speeds rarely broke above 200KB/s and were unreliable. The fastest I ever saw this framework get was around 1 MB/s. Other people's experience seem to mirror mine from what I've seen online.

2) NSNetService's discovery service in addition to it's ability to easily grab NSInputStream and NSOutputStreams. Using this in conjunction with the NSNetServices includePeerToPeer property allows me to easily and quickly connect to devices in a "true" peer to peer fashion and send data over the network using these streams. This would be great, but dealing with input and output streams is exceptionally complicated because I need to pack header data (incoming file name, size, location, etc) into the stream. I have this working in practice, but I'm uneasy with my implementation and feel as though there is no way I could cover all my bases. In a sense, I very much feel like I'm re-inventing the wheel here.

3) My ideal solution would use NSNetService's ability to detect and connect to peers as the last solution does, but would implement CocoaAsyncSockets to handle the actual file transfers, allowing me to use an established library with a proven track record that also lets me get away from the nitty gritty details of using NSInputStream and NSOutputStream.

The problem I'm having here is that while CocoaAsyncSockets work great when the devices are connected to the same network, they can't connect to each other on a true peer to peer network, presumably because they understandably can't see each other through the normal ethernet interfaces. It appears that the true peer to peer stuff uses Apple's awdl interface, which I've read on the developer forums cannot be used like a normal interface (I've tried specifying that interface when connecting the socket, it doesn't work).

I know this is rather vague, but does anyone have any suggestions for me? One of the developer's on the Apple developer forums mentioned something on a related topic about creating my own sockets from the sockets provided via the NSNetService when using publishWithOptions:NSNetServiceListenForConnections, but he didn't provide much information and I can't seem to figure out how that would work.

user3062913
  • 353
  • 2
  • 10
  • Did you find any solutions for this problem? I'm trying to achieve exactly the same, and have the same issues with AsyncSockets when connected directly. – Daniel Apr 24 '18 at 14:10
  • I wound up having to take the hard route and implement my own communications over NSInputStream and NSOutputStream as described in option 2. I could never get the CocoaAsyncSockets working for that one edge case. It's been 2 years, though. Is Apple's multipeer connectivity library any better than it used to be? Maybe you can just use that. I haven't worked on iOS since shortly after I made this post. – user3062913 Apr 25 '18 at 14:26
  • I tried Multipeer Connectivity, but when it comes to big files and reliability, it's just simply a disaster. I'm trying to move files around 1-300 MB. NSNetService and CocoaAsyncSockets just work wonderful together, if we have an access point, and it's super fast. So, probably I'll need to come up with my own solution handling the NSInputStreams.. if you have any code snippet you can share with me, just to navigate me to the right directions, I'd highly appreciate it. Thanks – Daniel Apr 25 '18 at 15:16
  • I would have gladly shared some code, but unfortunately I don't work anymore at the company where I wrote the code that did this! The basic summary as I remember it was that I followed the instructions you'll see online for opening input and output streams, then I just compiled a really simple header into the first packet that got sent out that indicated the full size of the file and sent it over. The receiving side would parse the header for size and just count received bytes and declare the file received when received bytes = header bytes. – user3062913 Apr 25 '18 at 20:50
  • Also, check out this [other question](https://stackoverflow.com/questions/38463642/writes-to-nsoutputstream-after-performing-work-on-background-thread-dont-work) I asked around the same period for some code and a little bit more insight. The takeaway from that thread is that you need to send keep alive packets over the socket if you plan on idling for any significant amount of time or the socket will automatically shut down. My application was doing a back and forth thing with processing in between, so it was necessary for me but if you're doing one file in one shot you won't have to worry. – user3062913 Apr 25 '18 at 20:56
  • Thanks for the insights, I'll try to come up with something, but this was useful to start! – Daniel Apr 26 '18 at 08:45

0 Answers0