/// <summary> /// Find a SmartSocketServer on the local network using UDP broadcast. This will block /// waiting for a server to respond or until you cancel using the CancellationToken. /// </summary> /// <returns>The connected client or null if task is cancelled.</returns> public static async Task <SmartSocketClient> FindServerAsync(string serviceName, string clientName, SmartSocketTypeResolver resolver, CancellationToken token, string udpGroupAddress = "226.10.10.2", int udpGroupPort = 37992) { return(await Task.Run(async() => { string localHost = FindLocalHostName(); if (localHost == null) { return null; } while (!token.IsCancellationRequested) { try { var groupAddr = IPAddress.Parse(udpGroupAddress); IPEndPoint remoteEP = new IPEndPoint(groupAddr, udpGroupPort); UdpClient udpClient = new UdpClient(0); MemoryStream ms = new MemoryStream(); BinaryWriter writer = new BinaryWriter(ms); writer.Write(serviceName.Length); writer.Write(serviceName); byte[] bytes = ms.ToArray(); udpClient.Send(bytes, bytes.Length, remoteEP); CancellationTokenSource receiveTaskSource = new CancellationTokenSource(); Task <UdpReceiveResult> receiveTask = udpClient.ReceiveAsync(); if (receiveTask.Wait(5000, receiveTaskSource.Token)) { UdpReceiveResult result = receiveTask.Result; IPEndPoint serverEP = result.RemoteEndPoint; byte[] buffer = result.Buffer; BinaryReader reader = new BinaryReader(new MemoryStream(buffer)); int len = reader.ReadInt32(); string addr = reader.ReadString(); string[] parts = addr.Split(':'); if (parts.Length == 2) { var a = IPAddress.Parse(parts[0]); SmartSocketClient client = await ConnectAsync(new IPEndPoint(a, int.Parse(parts[1])), clientName, resolver); if (client != null) { client.ServerName = serviceName; client.Name = localHost; return client; } } } else { receiveTaskSource.Cancel(); } } catch (Exception ex) { Debug.WriteLine("Something went wrong with Udp connection: " + ex.Message); } } return null; })); }
internal void RemoveClient(SmartSocketClient client) { bool found = false; lock (this.Clients) { found = this.Clients.Contains(client); this.Clients.Remove(client); } if (found && this.ClientDisconnected != null) { this.ClientDisconnected(this, client); } }
internal static async Task <SmartSocketClient> ConnectAsync(IPEndPoint serverEP, string clientName, SmartSocketTypeResolver resolver) { Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); bool connected = false; CancellationTokenSource src = new CancellationTokenSource(); try { Task task = Task.Run(() => { try { client.Connect(serverEP); connected = true; } catch (Exception e) { Debug.WriteLine("Connect exception: " + e.Message); } }, src.Token); // give it 30 seconds to connect... if (!task.Wait(60000)) { src.Cancel(); } } catch (TaskCanceledException) { // move on... } if (connected) { var result = new SmartSocketClient(null, client, resolver) { Name = clientName, ServerName = GetHostName(serverEP.Address) }; SocketMessage response = await result.SendReceiveAsync(new SocketMessage(ConnectedMessageId, clientName)); return(result); } return(null); }
internal async Task <bool> OpenBackChannel(SmartSocketClient client, int port) { if (this.BackChannelOpened != null) { IPEndPoint ipe = (IPEndPoint)client.Socket.RemoteEndPoint; IPEndPoint endPoint = new IPEndPoint(ipe.Address, port); SmartSocketClient channel = await SmartSocketClient.ConnectAsync(endPoint, this.ServiceName, this.Resolver); client.BackChannel = channel; this.BackChannelOpened(this, client); return(true); } else { // server is not expecting a backchannel! return(false); } }
private void UdpListenerThread() { try { var localHost = SmartSocketClient.FindLocalHostName(); List <string> addresses = SmartSocketClient.FindLocalIpAddresses(); if (localHost == null || addresses.Count == 0) { return; // no network. } IPEndPoint remoteEP = new IPEndPoint(this.GroupAddress, this.GroupPort); this.UdpListener = new UdpClient(this.GroupPort); this.UdpListener.JoinMulticastGroup(this.GroupAddress); while (true) { byte[] data = this.UdpListener.Receive(ref remoteEP); if (data != null) { BinaryReader reader = new BinaryReader(new MemoryStream(data)); int len = reader.ReadInt32(); string msg = reader.ReadString(); if (msg == this.ServiceName) { // send response back with info on how to connect to this server. IPEndPoint localEp = (IPEndPoint)this.Listener.LocalEndPoint; string addr = localEp.ToString(); MemoryStream ms = new MemoryStream(); BinaryWriter writer = new BinaryWriter(ms); writer.Write(addr.Length); writer.Write(addr); writer.Flush(); byte[] buffer = ms.ToArray(); this.UdpListener.Send(buffer, buffer.Length, remoteEP); } } } } catch (Exception) { // UdpListenerThread failed } }
private void OnAccept(Socket client) { IPEndPoint ep1 = client.RemoteEndPoint as IPEndPoint; SmartSocketClient proxy = new SmartSocketClient(this, client, this.Resolver) { Name = ep1.ToString(), ServerName = SmartSocketClient.FindLocalHostName() }; proxy.Disconnected += this.OnClientDisconnected; SmartSocketClient[] snapshot = null; lock (this.Clients) { snapshot = this.Clients.ToArray(); } foreach (SmartSocketClient s in snapshot) { IPEndPoint ep2 = s.Socket.RemoteEndPoint as IPEndPoint; if (ep1 == ep2) { // can only have one client using this end point. this.RemoveClient(s); } } lock (this.Clients) { this.Clients.Add(proxy); } if (this.ClientConnected != null) { this.ClientConnected(this, proxy); } }
private void OnClientDisconnected(object sender, EventArgs e) { SmartSocketClient client = (SmartSocketClient)sender; this.RemoveClient(client); }