public void StartClientDiscovery() { try { this.fileListener = new TcpListener(new IPEndPoint(IPAddress.Any, this.port + 1)); this.fileListener.Start(); this.Log().Info("Starting to listen for incoming file transfer connections on port {0}", this.port + 1); } catch (SocketException ex) { this.Log().ErrorException(String.Format("Port {0} is already taken", this.port), ex); this.isPortOccupied.OnNext(true); return; } try { this.messageListener = new TcpListener(new IPEndPoint(IPAddress.Any, this.port)); this.messageListener.Start(); this.Log().Info("Starting to listen for incoming message connections on port {0}", this.port + 1); } catch (SocketException ex) { this.fileListener.Stop(); this.Log().ErrorException(String.Format("Port {0} is already taken", this.port), ex); this.isPortOccupied.OnNext(true); return; } // We wait on a message and file transfer client that have the same origin address Observable.FromAsync(() => this.messageListener.AcceptTcpClientAsync()).Repeat() .MatchPair(Observable.FromAsync(() => this.fileListener.AcceptTcpClientAsync()).Repeat(), x => ((IPEndPoint)x.Client.RemoteEndPoint).Address) .Subscribe(sockets => { TcpClient messageTransferClient = sockets.Left; TcpClient fileTransferClient = sockets.Right; var mobileClient = new MobileClient(messageTransferClient, fileTransferClient, this.library); this.Log().Info("New client detected"); AnalyticsClient.Instance.RecordMobileUsage(); mobileClient.Disconnected.FirstAsync() .Subscribe(x => { mobileClient.Dispose(); lock (this.clientListGate) { this.clients.Remove(mobileClient); } }); mobileClient.ListenAsync(); lock (this.clientListGate) { this.clients.Add(mobileClient); } }).DisposeWith(this.listenerSubscriptions); }