GCDAsyncSocket server not connecting properly with multiple clients

903 views
Skip to first unread message

saini.v...@gmail.com

unread,
Nov 18, 2014, 5:42:41 PM11/18/14
to cocoaasy...@googlegroups.com
Hi

This is my first time using GCDAsyncSocket library and socket programming in general so I may be confused with some concepts. Sorry for that in advance. 

I have a GCDAsyncSocket server that connects fine with one GCDAsyncSocket client. But when there are 2 clients, it only connects to only one of them and stops. If I close the app and run it again then it sometimes connect to both (not always)

Similarly if I have say 8 clients, the first time it only connects to one of them. Second time it would connect to some of them but not all. Also, the connected devices are not necessarily same every time.

At this point, I am not sure if its threading issue or something else. My delegate queue is main queue so I am not sure what am I missing here. (I checked its the didAcceptNewSocket: method on the Publisher/Server side that does not get called for all of the client devices). Any help regarding this would be really appreciated.

Following is my Publisher/Server code:

 .
 
.
 
.
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: "", port:Int32(self.socket.localPort));


            // Configure Service

            self.service.delegate = self;

           self.service.includesPeerToPeer = true;

           self.service.publish();

       } else {

           println("Unable to create socket. Error \(error?.description) with user info \(error?.userInfo)");

       }

   }


    // MARK: Send Methods


    func sendPacket(packet: MPSocketPacket) {

       // Encode packet data

        var packetData = NSMutableData();

       let archiver = NSKeyedArchiver(forWritingWithMutableData: packetData);

       archiver.encodeObject(packet, forKey: "packet");

       archiver.finishEncoding();


        // Initialize Buffer

        var buffer = NSMutableData();


        // Fill Buffer

        var headerLength: UInt64 = UInt64(packetData.length);

       buffer.appendBytes(&headerLength, length: sizeof(UInt64));

       buffer.appendBytes(packetData.bytes, length: packetData.length);


        // Write Buffer

        self.socket.writeData(buffer, withTimeout: -1.0, tag: 0);

   }


    // 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)");

   }


    func netServiceDidStop(sender: NSNetService) {

       println("Bonjour Service stopped: domainName= \(sender.domain), type= \(sender.type), name= \(sender.name), onPort= \(sender.port)");

   }


    // MARK: GCDAsyncSocketDelegate method


    func socket(sock: GCDAsyncSocket!, didAcceptNewSocket newSocket: GCDAsyncSocket!) {

       println("Accepts new socket with host:\(newSocket.connectedHost) and port:\(newSocket.connectedPort))");


        // Read data from socket

        let size = sizeof(UInt64);

       newSocket.readDataToLength(UInt(size), withTimeout: -1.0, tag: 0);


       dispatch_async(dispatch_get_main_queue(), {
            self.connectedSockets.append(newSocket);

           println("Connected sockets are  \(self.connectedSockets)");
         });

      // Create Packet

        let message = "Testing Proof of concept";

       let packet = MPSocketPacket(packetData: message, packetType: .Unknown, packetAction: .Unknown);

       self.sendPacket(packet, toPeers: [newSocket]);

   }


    func socketDidDisconnect(sock: GCDAsyncSocket!, withError err: NSError!) {

    //   println("Socket with host:\(sock.connectedHost) and port:\(sock.connectedPort) is disconnected");


        if (sock != nil) {

           for (index, socket) in enumerate(self.connectedSockets) {

               if (socket == sock) {

                   socket.delegate = nil;

                   self.connectedSockets.removeAtIndex(index);

               }

           }

       } else {

           println("Nil socket is returned");

           println("Socket is connected: \(self.socket.isConnected) to address: \(self.socket.connectedHost)");

       }

   }


    deinit {

       self.stopPublishing();
   
}

 .
 
.
 
.


This is the Publisher/Server console output

Bonjour Service published: domainName= local., type= _mpstest._tcp., name= iPad 29, onPort= 56256

Accepts new socket with host:169.254.83.213 and port:52838)

Connected sockets are  [<GCDAsyncSocket: 0x1763f950>]


Following is my Browser/Client code:

 .
 
.
 
.

   private func resolveServiceAddresses() {

      self.advertiserService.delegate = self;

      self.advertiserService.resolveWithTimeout(30.0);

  }


    private func connectWithService(service: NSNetService, hostname: String) ->Bool {

      var isConnecting:Bool = false;


        if (self.browserSocket == nil || !(self.browserSocket?.isConnected)!) {

          // Initialize Socket

            self.browserSocket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue());


            // Connect

            while (!isConnecting){

              var error: NSError?;

              println("Connecting port : \(service.port) and hostname: \(hostname)");

              if (self.browserSocket.connectToHost(hostname, onPort: UInt16(service.port), 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;

  }


    private func parseHeader(data: NSData) -> UInt64 {

      var headerLength: UInt64 = 0;

      memcpy(&headerLength, data.bytes, UInt(sizeof(UInt64)));

      return headerLength;

  }


    private func parseBody(data: NSData) {

      let unarchiver = NSKeyedUnarchiver(forReadingWithData: data);

      let packet = unarchiver.decodeObjectForKey("packet") as MPSocketPacket;

      unarchiver.finishDecoding();

       println("Packet Data : \(packet.data)");

      println("Packet Type : \(packet.type)");

      println("Packet Action : \(packet.action)");

  }


    // 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.advertiserService = aNetService;


        if (!moreComing) {

          println("Service found is : \(aNetService)");

          self.resolveServiceAddresses();

      }

  }


    func netServiceBrowser(aNetServiceBrowser: NSNetServiceBrowser, didRemoveService aNetService: NSNetService, moreComing: Bool) {

      // Update Services which have stopped

       self.advertiserService.delegate = nil;

      self.advertiserService = nil;


        if (!moreComing) {

          println("Service left after removing are : \(self.advertiserService?)");

      }

  }


    // 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, hostname: sender.hostName!)) {

          println("Connected with service: domainName= \(sender.domain), type= \(sender.type), name= \(sender.name), onPort= \(sender.port) and hostname: \(sender.hostName!)");

      } 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("Socket: \(sock) 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 \(sock) did disconnect with error \(err?)");

  }


    func socket(sock: GCDAsyncSocket!, didReadData data: NSData!, withTag tag: Int) {

      if (tag == 0) {

          let bodyLength: UInt64 = self.parseHeader(data);

          sock.readDataToLength(UInt(bodyLength), withTimeout: 30.0, tag: 1);

      } else if (tag == 1) {

          self.parseBody(data);

          sock.readDataToLength(UInt(sizeof(UInt64)), withTimeout: -1.0, tag: 0);

      }

  }

 .
 
.
 
.




This is the connected Browser/Client console output:

Service found is : <NSNetService 0x17e6df50> local. _mpstest._tcp. iPad 29

Connecting port : 56212 and hostname: iPad-29.local.

Connected with service: domainName= local., type= _mpstest._tcp., name= iPad 29, onPort= 56212 and hostname: iPad-29.local.

is it main thread true

Service left after removing are : nil

Service found is : <NSNetService 0x17e526d0> local. _mpstest._tcp. iPad 29

Connecting port : 56212 and hostname: iPad-29.local.

Connected with service: domainName= local., type= _mpstest._tcp., name= iPad 29, onPort= 56212 and hostname: iPad-29.local.

Socket nil did disconnect with error nil

Socket: <GCDAsyncSocket: 0x17e7f690> Did connect to host: 169.254.140.21 on port:56212

Packet Data : Testing Proof of concept

Packet Type : (Enum Value)

Packet Action : (Enum Value)


These are the Not Connected Browser/Client console output:

Service found is : <NSNetService 0x16d9e860> local. _mpstest._tcp. iPad 29

Connecting port : 56212 and hostname: iPad-29.local.

Connected with service: domainName= local., type= _mpstest._tcp., name= iPad 29, onPort= 56212 and hostname: iPad-29.local.

Socket <GCDAsyncSocket: 0x16eaca80> did disconnect with error Optional(Error Domain=NSPOSIXErrorDomain Code=60 "Operation timed out" UserInfo=0x16d9ec30 {NSLocalizedFailureReason=Error in connect() function, NSLocalizedDescription=Operation timed out})


OR this (sometimes):

Service found is : <NSNetService 0x15538da0> local. _mpstest._tcp. iPad 29

Connecting port : 56256 and hostname: iPad-29.local.

Connected with service: domainName= local., type= _mpstest._tcp., name= iPad 29, onPort= 56256 and hostname: iPad-29.local.

Socket <GCDAsyncSocket: 0x1565df50> did disconnect with error Optional(Error Domain=kCFStreamErrorDomainNetDB Code=8 "nodename nor servname provided, or not known" UserInfo=0x1564cee0 {NSLocalizedDescription=nodename nor servname provided, or not known})


Once again, I would really appreciate any help/suggestions regarding this.

Thanks
Vik
Reply all
Reply to author
Forward
0 new messages