/// <summary> /// Start a new server that listens for connections from anyone. /// </summary> /// <param name="name">The unique name of the server</param> /// <param name="resolver">For resolving custom message types received from the client</param> /// <param name="ipAddress">Determines which local network interface to use</param> /// <param name="udpGroupAddress">Optional request to setup UDP listener, pass null if you don't want that</param> /// <param name="udpGroupPort">Optional port required if you provide udpGroupAddress</param> /// <returns>Returns the new server object</returns> public static SmartSocketServer StartServer(string name, SmartSocketTypeResolver resolver, string ipAddress = "127.0.0.1", string udpGroupAddress = "226.10.10.2", int udpGroupPort = 37992) { SmartSocketServer server = new SmartSocketServer(name, resolver, ipAddress, udpGroupAddress, udpGroupPort); server.StartListening(); return(server); }
internal SmartSocketClient(SmartSocketServer server, Socket client, SmartSocketTypeResolver resolver) { this.client = client; this.stream = new NetworkStream(client); this.server = server; this.resolver = resolver; client.NoDelay = true; DataContractSerializerSettings settings = new DataContractSerializerSettings(); settings.DataContractResolver = this.resolver; settings.PreserveObjectReferences = true; this.serializer = new DataContractSerializer(typeof(MessageWrapper), settings); }
/// <summary> /// Initializes a new instance of the <see cref="SmartSocketServer"/> class. /// </summary> /// <param name="name">The name the client will check in UDP broadcasts to make sure it is connecting to the right server</param> /// <param name="resolver">A way of providing custom Message types for serialization</param> /// <param name="ipAddress">An optional ipAddress so you can decide which network interface to use</param> private SmartSocketServer(string name, SmartSocketTypeResolver resolver, string ipAddress = "127.0.0.1", string udpGroupAddress = "226.10.10.2", int udpGroupPort = 37992) { this.serviceName = name; this.resolver = resolver; this.ipAddress = IPAddress.Parse(ipAddress); if (!string.IsNullOrEmpty(udpGroupAddress)) { this.GroupAddress = IPAddress.Parse(udpGroupAddress); this.GroupPort = udpGroupPort; } }
/// <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 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); }