/// <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 (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 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 UdpListenerThread() { var localHost = SmartSocketClient.FindLocalHostName(); List <string> addresses = SmartSocketClient.FindLocalIpAddresses(); if (localHost == null || addresses.Count == 0) { return; // no network. } IPEndPoint remoteEP = new IPEndPoint(GroupAddress, GroupPort); this.udpListener = new UdpClient(GroupPort); this.udpListener.JoinMulticastGroup(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); } } } }
private void OnClientDisconnected(object sender, EventArgs e) { SmartSocketClient client = (SmartSocketClient)sender; this.RemoveClient(client); }