I have an IoT application that uses Socket Programming to communicate with the device. All good up until iOS 11 released. It doesn't communicate in iOS 11 and above but it works in earlier versions ( Up to 10). Here is the code.
Establishing Socket Connection
(void)setUpSocketConnection {
@try {
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef) VeranoHost,VeranoPort , &readStream, &writeStream);
[self open];
}
@catch (NSException *exception) {
NSLog(@"Open Exception:%@", exception.reason);
}
}
Opening Streams
(void)open {
//NSLog(@"Opening streams.");
_outputStream = (__bridge NSOutputStream *)writeStream;
_inputStream = (__bridge NSInputStream *)readStream;
[_outputStream setDelegate:self];
[_inputStream setDelegate:self];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);
dispatch_async(queue, ^ {
[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
[_outputStream open];
[_inputStream open];
//[self disableNaglesAlgorithmForStream:_inputStream];
// NSLog(@"Connected");
// self.timeOutTimer = [NSTimer scheduledTimerWithTimeInterval:10.0
// target:self
// selector:@selector(timerTimeOutAction:)
// userInfo:nil
// repeats:NO];
}
Writing to Output Stream
(void)writeData:(NSString *)message forSocketType:(SOCKETTTYPE)socketType {
self.socketType = socketType;
NSData *data = [[NSData alloc] initWithData:[message dataUsingEncoding:NSASCIIStringEncoding]];
[_outputStream write:[data bytes] maxLength:[data length]];
[_outputStream close];
}
Event Handler
(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
// NSLog(@"stream event %lu", (unsigned long)streamEvent);
switch (streamEvent) {
case NSStreamEventOpenCompleted:{
// NSLog(@"NSStreamEventOpenCompleted :::: Stream opened and connected");
}
break;
case NSStreamEventHasBytesAvailable:
// NSLog(@"NSStreamEventHasBytesAvailable :::: Stream opened and connected");
if (theStream == _inputStream) {
uint8_t buffer[1024];
NSInteger len;
while ([_inputStream hasBytesAvailable])
{
len = [_inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0)
{
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if (nil != output)
{
NSLog(@"server said: %@", output);
[self messageReceived:output];
}
}
}
}
break;
case NSStreamEventHasSpaceAvailable:
// NSLog(@"NSStreamEventHasSpaceAvailable :::: Stream has space available now");
break;
case NSStreamEventErrorOccurred:{
NSError *theError = [theStream streamError];
NSLog(@"Error Description:%@",theError.localizedDescription);
[self close];
if(self.delegate &&[self.delegate respondsToSelector:@selector(socketHandlerItem:failureWithError:forSocketType:)]){
[self.delegate socketHandlerItem:self failureWithError:[theStream streamError] forSocketType:self.socketType];
}
//NSLog(@"NSStreamEventErrorOccurred :::: %@",[theStream streamError].localizedDescription);
}
break;
case NSStreamEventEndEncountered:
[theStream close];
[theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
if(self.delegate &&[self.delegate respondsToSelector:@selector(socketHandlerItem:eventStopedWithstatus:forSocketType:)]){
[self.delegate socketHandlerItem:self eventStopedWithstatus:YES forSocketType:self.socketType];
}
// NSLog(@"NSStreamEventEndEncountered :::: close stream Disconnected");
break;
default:
// NSLog(@"Unknown event");
break;
}
}
So, when connecting to the socket it enters to the
NSStreamEventErrorOccurred
in the event handler and logs -The operation couldn’t be completed. No route to host
Any help would be greatly appreciated.
Update Dec 19, 2017
- Got a Reachability wrapper that allows to discover host address and I can confirm that it returns the NetworkStatus
ReachableViaWiFi
- Socket communication works fine, I tried by creating a sample server socket, able to send and receive data.
Update Dec 20, 2017 (1)
IoT device Details -
USR-WIFI232-S
Low Power WiFi ModuleUser Manual Here
Update Dec 20, 2017 (2)
Eurekaa, but the solution can't be applied in real time. While setting a nearest range of static IP address in iOS 11 corresponding to IoT module's host address the communication works fine. but it doesn't work with the dynamically allocated IP address.