Hi All, I have coded a TCP Server packaged inside C++ static library. I am using this static library within the iOS Swift UI application. I have coded a simple UI which has a button, on click of which I want to start the TCP server (which is written in C++ and inside the linked static library). After the TCP server is started, I want to push the application to background and then run the client application which is going to interact with this TCP server from the backgrounded SwiftUI application. I want the TCP server to be running even the application goes to the background mode as I have another user interface application which is going to interact with the TCP server on the same device. I tried using background task, but I don't know whether I am doing something wrong there, or I cannot achieve what I want using the BackgroundTask functionality available in iOS. The main thing here is, the TCP server code is in C++ inside static library and I want to start the TCP server from SwiftUI application layer. I have managed to call C++ function from Swift that part is available. Can anyone show me the right path here ? How do I keep the BSD Socket based TCP Server active while the application is in Background mode ?
BSD Socket TCP Server in background : swift with C++
Just FYI, Apple considers BSD Sockets to be a legacy technology and we encourage folks to switch to the Network framework. If you have existing BSD Sockets code it’s fine to keep using it — we will continue supporting that API because of its cross-platform nature — but you’ll be missing out on all the new stuff that we’re adding to Network framework.
Having said that, the problem you’re seeing here is fundamental to iOS’s architecture and affects all networking APIs. For more background, see Technote 2277 Networking and Multitasking. In short:
-
Networking works just fine in the background as long as your app is running.
-
However, iOS suspends apps shortly after you move them to the background, and at that point all networking stops.
There are various fixes you can apply here, depending on your specific circumstances. However this:
I want the TCP server to be running even the application goes to the background mode as I have another user interface application which is going to interact with the TCP server on the same device.
is unlikely to be feasible. Using a background app as an IPC service is simply not supported on iOS. You may be able to make limit progress down this path, but it’s a rocky road that will eventually lead you off a cliff.
What does this background service do?
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Thank you eskimo for your quick response here. Even I was suspecting same that this approach of running the IPC mechanism in background will make me jump off a cliff at one point in future. In that case, what would be the better approach to implement this silently running TCP server in iOS environment ?? What does this background service do? The background service is just a TCP server which fulfils request that comes from another application. There are other application which needs our background tcp server to fulfil their requirements. Hence, we thought of running the TCP server as background which user need not know about. Also, I would really appreciate if you could guide me in terms of right approach to have a TCP server along with our other apps which needs this TCP server to fulfil their request. Thank you in advance. Regards, Mandar
Also, what is that you mentioned about "Network framework." means ? How can I use that for my use case ?? Is there any example for usage of Network Framework ? Also, Is it possible to have TCP server running from Swift app which can handle the background mode in it ??
Also, what is that you mentioned about "Network framework." means ?
To be clear, Network framework won’t let you achieve the specific goal raised in this thread. It has exactly the same constraints as BSD Sockets when it comes to running in the background.
I would really appreciate if you could guide me in terms of right approach to have a TCP server along with our other apps which needs this TCP server to fulfil their request.
There is no “right approach” here. Your current design is fundamentally incompatible with iOS’s background execution model.
Note I have an iOS Background Execution Limits post that explains the limits of this model, and I’ve added your scenario to the list of common questions.
Folks generally get around this in one of two ways:
-
Move the service off the device and on to a network server.
-
Distribute the work to all the apps, sharing state via an App Group.
If you want more specific advice then you’ll need to post more details about the service you’re trying to implement. To be clear, this:
The background service is just a TCP server which fulfils request that comes from another application.
is too vague for me to offer you specific advice. I need to know things like:
-
Are all the apps involved published by the same team?
-
What is the nature of your IPC requests? How large are they? How frequent are they? What are the latency contraints?
-
Are your clients always in the foreground? Or is it possible that a client could itself be in the background when it issues a request?
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Hi Eskimo, I really. appreciate your quick response. Below are my comments and answers for few questions you had asked. I really need some direction here as this issue is getting hotter for our app and the whole team. Need to find out some solution for this which can sustain for longer time. Please help me here.
Let me explain the scenario about the how the background service is going to be consumed.
There are two different apps, App-1 and App-2. App-1 fulfils requests from App-2. App-1 needs to have a locally running server which can function in offline case as well when there is no internet as well. This is requirement. Hence, we cannot rely on some web-server/service which can act as App-1 to fulfil request from App-2 as it would add hard dependency on internet network. App-2 has a small client module, which we provide, integrated into it, which interacts with the service of App-1 and get the specific functionality request fulfilled. Both the apps are developed by two different teams. We are working on App-1 which provides the service to App-2 and both the apps are to be used within our organisation boundary itself, I mean by our organisation employees only (This is decided to be like this as of now. Later we may plan to make it a global app and plan to upload it to Appstore as well. But nothing of that is planned as of now).
I hope this gives a good background about the execution environment now.
Below are the answers to your questions :
Eskimo : Are all the apps involved published by the same team? Mandar: No, both the apps, App-1 and App-2, are not published by same team. Two different teams are working on these two apps. My team works on App-1 which provides the client module for App-2 to integrate in their app, which interacts with our server on App-1.
Eskimo: What is the nature of your IPC requests? How large are they? How frequent are they? What are the latency contraints? Mandar: The size of data that is being exchanged in IPC is small It is not even in MB's. It is just that we have placed our own security check in the IPC hence we are using TCP server/client approach for IPC. If any other such framework already available from Apple for iOS we would like to explore that which would not let to compromise our security measures for securing data that is being exchanged over IPC communication. If we talk of latency, we cannot afford to have the "Server not running" otherwise the App-2 will fail in functionality at that moment which is required by user. Hence, we need to have the server in App-1 running at the time, when the App-2 needs its request to be fulfilled. If it can be possible to wake-up the server in App-1 for the moment of time, when the App-2 has some request for server, that would be the best solution for us and the iOS. Frequency of the request is not fixed it can be once in an hour or twice in a minute as well. So there is no fixed time or frequency of the IPC request. **Main thing is both App-1 and App-2 should be able to communicate and function in offline case, when there is no internet connectivity. **
Eskimo: Are your clients always in the foreground? Or is it possible that a client could itself be in the background when it issues a request? Mandar: Clients will always be in foreground at the time of IPC request. There won't be any client request when the Client app goes in background. Considering above scenario I have explained, App-2 shall always be in foreground at the time of sending IPC request.
I have a question below about the workaround or kind of solution that I am thinking.
If I implement background fetch in App-1 where-in I start the TCP server in background fetch activity, is there way to locally send trigger from App-2 to App-1 in order to trigger/wake-up the App-1 for a moment of time in the background so that the IPC request from App-2 gets fulfilled at that moment of time, then again the App-1 can go in suspended mode ? Will the notification mechanism help us solve our problem of triggering the App-1 from App-2 just before sending the IPC request ?
Thank you once again Eskimo for your prompt response. Me and my time highly appreciate it. Please help me out of this situation its really getting worse day by day.
Regards, Mandar
Thanks for all the answers so far.
We are working on App-1 which provides the service to App-2 and both the apps are to be used within our organisation boundary itself, I mean by our organisation employees only
Hmmm, I think the jargon on my queue caused you to misunderstand it. When I wrote “Are all the apps involved published by the same team?” I was using “team” in a very specific technical sense. Namely, are they published by the same as defined in the Manage your team section of Developer Account Help?
This matters because the iOS sandbox offers more IPC facilities to apps from the same team.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
So “jargon on my queue” should have been “jargon in my question”.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Oh, that's what you meant by teams. I must admit that I am new to the iOS development, so I am not much aware about such jargons. As per my understanding, both the apps, App-1 and App-2 are going to be developed using the profile generated by our enterprise apple account. Does that simplify the problem of IPC communication between App-1 and App-2 ?
The only thing to note here is that, both the apps are being developed by two different development teams.
Could you please elaborate more on the below statement of yours ?
"This matters because the iOS sandbox offers more IPC facilities to apps from the same team."
Does that simplify the problem of IPC communication between App-1 and App-2?
Yes. iOS goes out of its way to isolate apps in their own sandbox, but it relaxes that isolation somewhat for apps from the same team. For example, apps from the same team can share context via a custom pasteboard.
Having said that, this won’t solve your IPC problem. The crux of that problem is that, in order to service any sort of IPC request, App-1 must be running in the background and, by default, iOS suspends apps when they go to the background. There is no general-purpose mechanism for the system to resume your app in the background in response to an IPC request. You could try to achieve this by abusing one of the existing background execution models but I strongly recommend against that. Again, my iOS Background Execution Limits post has more on this.
And that brings me to a point I made earlier, namely:
Distribute the work to all the apps, sharing state via an App Group.
The idea here is to move away from a client/server model and instead add your core code to each client app (typically as a framework). That code can then store its persistent state in an App Group. This works because:
-
When the client app performs an operation it’s in the foreground and thus won’t be suspended.
-
The client apps can share state in an App Group because they’re all published by the same team.
The key challenges related to state management:
-
In a client/server model it’s easy for the server to keep its in-memory state in sync with it’s persistent state. That’s not the case with this distributed model.
-
iOS can have multiple apps running at one — most commonly via iPad multitasking but it can happen other ways as well — so each client app does not have exclusive access to the persistent state.
-
Because your code is embedded in the client apps it’s possible that different versions of your code can be operating on your persistent state simultaneously.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Thank you Eskimo for detailed explanation here. Looks like there is need to change our app design in-order to achieve the functionality we need. I personally do not like to do anything violating any rules/guidelines of the OS, definitely not.
It would be really helpful if you point me to some place where I can explore more on the below point you mentioned.
"Yes. iOS goes out of its way to isolate apps in their own sandbox, but it relaxes that isolation somewhat for apps from the same team. For example, apps from the same team can share context via a custom pasteboard."
I would like to read more about the above option.
Also, what is the code security level for the framework ? I mean is it possible to decompile the framework if it goes in wrong hands ?
I really thank you for your continuous guidance Eskimo. I really needed this guidance.
It would be really helpful if you point me to some place where I can explore more on the below point you mentioned.
Yes. iOS goes out of its way to isolate apps in their own sandbox, but it relaxes that isolation somewhat for apps from the same team. For example, apps from the same team can share context via a custom pasteboard.
I would like to read more about the above option.
Most of that info is spread across various API references. For example, for the specific pasteboard case I called out, the UIPasteboard
documentation says:
You can create named pasteboards … for sharing data within your app and from your app to other apps that have the same Team ID.
AFAIK there isn’t a good overview doc for the iOS sandbox as a whole. However, I do recommend the following:
-
Apple Platform Security — This covers the overall iOS security architecture and makes for very interesting reading.
-
App Sandbox Design Guide — This covers the App Sandbox on macOS. While the two platforms differ considerably, many of the concepts apply to both. For example, on macOS the user extends your sandbox using the open and save dialogs, whereas on iOS they do the same thing using APIs like
UIDocumentPickerViewController
.
Also, what is the code security level for the framework ? I mean is it possible to decompile the framework if it goes in wrong hands ?
Yes.
There are some things that mitigate this:
-
If you distribute your code via the App Store, some of it is protected by FairPlay DRM.
-
The fact that you ship native code makes it harder to decompile.
-
Our tools have options to strip symbols (except the ones needed by the dynamic linker and the Swift and Objective-C runtimes).
-
The Swift compiler has options to limit the amount of runtime introspection it supports.
However, your goal here is DRM — you want to give someone your code but limit what they can do with it — and all DRM systems have limits. You should assume that a determined attacker can read your code.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"