Simple iOS App with Foundation InputStream and OutputStream...


bap04e@...
 

All,


I created a simple iOS app to connect to a server and receive a message. I am doing this as an example app using InputStream, OutputStream, and StreamDelegate. The Server is a simple Java app running on my MacBook Pro. The iOS app is running on my iPhone 7. I use the address of my laptop on the local network and the port the Java app is listening on (xxx.xxx.xxx.xxx:ppppp) in the URL object. Despite this, my InputStream and OutputStream objects are nil after calling their initializers. If I use netcat in terminal I can connect to the server. But my running iOS app cannot. Is there something missing in the iOS app that I need, like a permission of some sort?


 

On Nov 15, 2017, at 8:25 AM, Brandon Peters <bap04e@...> wrote:

All,

I created a simple iOS app to connect to a server and receive a message. I am doing this as an example app using InputStream, OutputStream, and StreamDelegate.
Consider using NSURLSessionStreamTask; it’s higher-level with IMHO a better API, and it supports proxies.

The Server is a simple Java app running on my MacBook Pro. The iOS app is running on my iPhone 7. I use the address of my laptop on the local network and the port the Java app is listening on (xxx.xxx.xxx.xxx:ppppp) in the URL object. Despite this, my InputStream and OutputStream objects are nil after calling their initializers.
If you’re using an NSURL for this, I don’t think you’re doing it correctly. URLs have schemes, which identify what protocol to use. Since you’re just making a raw TCP connection you don’t have a defined protocol that NSURL knows about.

The API for creating raw NSStreams for a TCP client connection is +[NSStream getStreamsToHostWithName:…].

—Jens


Brandon Peters <bap04e@...>
 

Jens,

Thanks for reply. I thought the +[NSStream getStreamsToHostWithName:…] was deprecated in iOS 11+?

--Brandon

On Nov 15, 2017, at 12:41, Jens Alfke <jens@...> wrote:



On Nov 15, 2017, at 8:25 AM, Brandon Peters <bap04e@...> wrote:

All,

I created a simple iOS app to connect to a server and receive a message. I am doing this as an example app using InputStream, OutputStream, and StreamDelegate.

Consider using NSURLSessionStreamTask; it’s higher-level with IMHO a better API, and it supports proxies.

The Server is a simple Java app running on my MacBook Pro. The iOS app is running on my iPhone 7. I use the address of my laptop on the local network and the port the Java app is listening on (xxx.xxx.xxx.xxx:ppppp) in the URL object. Despite this, my InputStream and OutputStream objects are nil after calling their initializers.

If you’re using an NSURL for this, I don’t think you’re doing it correctly. URLs have schemes, which identify what protocol to use. Since you’re just making a raw TCP connection you don’t have a defined protocol that NSURL knows about.

The API for creating raw NSStreams for a TCP client connection is +[NSStream getStreamsToHostWithName:…].

—Jens





 



On Nov 15, 2017, at 9:48 AM, Brandon Peters <bap04e@...> wrote:

Thanks for reply. I thought the +[NSStream getStreamsToHostWithName:…] was deprecated in iOS 11+?

Just take a look at the header. It’s only the older version that takes an NSHost that’s deprecated:

@interface NSStream (NSSocketStreamCreationExtensions)

+ (void)getStreamsToHostWithName:(NSString *)hostname port:(NSInteger)port inputStream:(NSInputStream * _Nullable * _Nullable)inputStream outputStream:(NSOutputStream * _Nullable * _Nullable)outputStream API_AVAILABLE(macos(10.10), ios(8.0), tvos(9.0)) __WATCHOS_PROHIBITED;

#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
+ (void)getStreamsToHost:(NSHost *)host port:(NSInteger)port inputStream:(NSInputStream * _Nullable * _Nullable)inputStream outputStream:(NSOutputStream * _Nullable * _Nullable)outputStream API_DEPRECATED("Please use getStreamsToHostWithName:port:inputStream:outputStream: instead", macos(10.3,10.10)) API_UNAVAILABLE(ios, watchos, tvos);
#endif

@end


listservices@...
 

Hi Brandon.
 
One other consideration with iOS is that you may need to whitelist the destinations you want to connect to by declaring them in your info.plist under the NSAppTransportSecurity key. I don’t know if this applies to streams or not(?). 
 
In any event, this is done in your app's info.plist. Here is some sample XML with some different options you might need. I’ve added some explanatory comments. For the official guide, go here:
 
 
and search for NSAppTransportSecurity on the page.
 
 
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key> // As you might expect, this lets you load from arbitrary locations which can be useful during development
<true/>
<key>NSExceptionDomains</key>. // The domains you are going to whitelist go here
<dict>
<key>akamaihd.net</key> // The domain (or subdomain) you want to whitelist.
<dict>
<key>NSIncludesSubdomains</key> // In this case, any akamaihd.net subdomain is allowed. 
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key> 
<false/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> // This allows non https loads, which are blocked by default.
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
<key>NSTemporaryExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
</dict>
 
Hopefully this is helpful.
 
— Erikheath