I am really new to the Network Programming and trying to implement an app in iOS8/Swift using GCDAsyncSocket framework. I am able to publish the service from host device. The service is being found by the browser device but when the browser tries to connect to the host, they never connect and socketDidDisconnect method is returned on the browser device with "Operation Timed Out" error even though I have not set any timeout limit.
Following is my Browser code:
private func resolveServiceAddresses() {
for service in self.services {
service.delegate = self;
service.resolveWithTimeout(30.0);
}
}
private func connectWithService(service: NSNetService) -> Bool {
var isConnecting:Bool = false;
//Copy Service Addresses
let addresses = service.addresses;
if (self.browserSocket == nil || !(self.browserSocket?.isConnected)!) {
// Initialize Socket
self.browserSocket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue());
// Connect
while (!isConnecting && (addresses?.count > 0 )){
let address = addresses?[0] as NSData;
var error: NSError?;
if (self.browserSocket.connectToAddress(address, error: &error)) {
isConnecting = true;
} else if (error != nil) {
println("Unable to connect to address. Error \(error) with user info \(error?.userInfo)");
}
}
} else {
println("Connecting is: \(self.browserSocket.isConnected)");
isConnecting = self.browserSocket.isConnected;
}
return isConnecting;
}
// MARK: NSNetServiceBrowserDelegate methods
func netServiceBrowser(aNetServiceBrowser: NSNetServiceBrowser, didFindService aNetService: NSNetService, moreComing: Bool) {
// This device is not advertising/publishing. So don't need any test before updating servies
self.services.append(aNetService);
if (!moreComing) {
println("Service found is : \(aNetService)");
self.resolveServiceAddresses();
}
}
// MARK: NSNetServiceDelegate methods
func netService(sender: NSNetService, didNotResolve errorDict: [NSObject : AnyObject]) {
sender.delegate = nil;
println("Did not resolve service: domain:\(sender.domain) type:\(sender.type) name:\(sender.name) on port: \(sender.port) with error: \(errorDict)");
}
func netServiceDidResolveAddress(sender: NSNetService) {
// Connect with Service
if (self.connectWithService(sender)) {
println("Connecting with service: domainName= \(sender.domain), type= \(sender.type), name= \(sender.name), onPort= \(sender.port)");
} else {
println("Unable to connect with service: domainName= \(sender.domain), type= \(sender.type), name= \(sender.name), onPort= \(sender.port)");
}
}
// GCDAsyncSocketDelegate methods
func socket(sock: GCDAsyncSocket!, didConnectToHost host: String!, port: UInt16) {
println("Did connect to host: \(host) on port:\(port)");
// Start Reading
sock.readDataToLength(UInt(sizeof(UInt64)), withTimeout: -1.0, tag: 0);
}
func socketDidDisconnect(sock: GCDAsyncSocket!, withError err: NSError!) {
println("Socket did disconnect with error \(err?)");
}
Following is the console log for the Browser device:
Service found is : <NSNetService 0x1454b490> local. _mpstest._tcp. iPad 30
Connecting with service: domainName= local., type= _mpstest._tcp., name= iPad 30, onPort= 50490
Connecting with service: domainName= local., type= _mpstest._tcp., name= iPad 30, onPort= 50490
Socket did disconnect with error nil
Socket did disconnect with error Optional(Error Domain=NSPOSIXErrorDomain Code=60 "Operation timed out" UserInfo=0x1465c350 {NSLocalizedFailureReason=Error in connect() function, NSLocalizedDescription=Operation timed out})
and here is the Publisher/Host code:
override func viewDidLoad() {
super.viewDidLoad()
// Publish the service
self.publishService();
}
// MARK: Button callbacks
private func publishService() {
// Initialize GCDAsyncSocket
self.socket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue());
// Start listening for incoming connections
var error: NSError?;
if (self.socket.acceptOnPort(0, error: &error)) {
// Initialize Service
self.service = NSNetService(domain: "local.", type: "_mpstest._tcp", name: UIDevice.currentDevice().name, port:0);
// Configure Service
self.service.delegate = self;
self.service.includesPeerToPeer = true;
self.service.publishWithOptions(.ListenForConnections);
} else {
println("Unable to create socket. Error \(error?.description) with user info \(error?.userInfo)");
}
}
// MARK: NSNetServiceDelegate Methods
func netServiceDidPublish(sender: NSNetService) {
println("Bonjour Service published: domainName= \(sender.domain), type= \(sender.type), name= \(sender.name), onPort= \(sender.port)");
}
func netService(sender: NSNetService, didNotPublish errorDict: [NSObject : AnyObject]) {
println("Failed to publish service: domainName= \(sender.domain), type= \(sender.type), name= \(sender.name), onPort= \(sender.port) error= \(errorDict)");
}
// MARK: GCDAsyncSocketDelegate method
func socket(sock: GCDAsyncSocket!, didAcceptNewSocket newSocket: GCDAsyncSocket!) {
println("Local socket with host:\(sock.connectedHost) and port:\(sock.connectedPort) accepts new socket with host:\(newSocket.connectedHost) and port:\(newSocket.connectedPort))");
// Updating socket
self.socket = newSocket;
//Read data from socket
let size = sizeof(UInt64);
newSocket.readDataToLength(UInt(size), withTimeout: -1.0, tag: 0);
}
func socketDidDisconnect(sock: GCDAsyncSocket!, withError err: NSError!) {
println("Socket with host:\(sock.connectedHost) and port:\(sock.connectedPort) is disconnected");
if (self.socket == sock) {
self.socket.delegate = nil;
self.socket = nil;
}
}
Following is the console log for Publisher/Host:
Bonjour Service published: domainName= local., type= _mpstest._tcp., name= iPad 30, onPort= 50490
I am stuck here. So any help would be greatly appreciated.