| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- using System.Text.Json;
- using NetworkTool.Client.Models;
- namespace NetworkTool.Client.Services;
- public sealed class DiscoveryService
- {
- private const int DiscoveryPort = 50000;
- public async Task<DiscoveredDevice?> DiscoverAsync(string localIPv4, CancellationToken cancellationToken = default)
- {
- if (string.IsNullOrWhiteSpace(localIPv4))
- {
- return null;
- }
- using var client = new UdpClient(AddressFamily.InterNetwork)
- {
- EnableBroadcast = true,
- };
- client.Client.Bind(new IPEndPoint(IPAddress.Parse(localIPv4), 0));
- var request = new
- {
- protocol_version = 1,
- message_type = "discover",
- request_id = Guid.NewGuid().ToString(),
- client_name = Environment.MachineName,
- };
- var payload = JsonSerializer.SerializeToUtf8Bytes(request);
- await client.SendAsync(payload, payload.Length, new IPEndPoint(IPAddress.Broadcast, DiscoveryPort));
- using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
- timeoutCts.CancelAfter(TimeSpan.FromSeconds(3));
- try
- {
- var result = await client.ReceiveAsync(timeoutCts.Token);
- var response = JsonSerializer.Deserialize<DiscoveryResponse>(result.Buffer);
- if (response is null || response.MessageType != "discover_response")
- {
- return null;
- }
- return new DiscoveredDevice
- {
- DeviceId = response.DeviceId ?? string.Empty,
- Hostname = response.Hostname ?? string.Empty,
- ServerVersion = response.ServerVersion ?? string.Empty,
- Lan2Ip = response.Lan2Ip ?? string.Empty,
- AuthRequired = response.AuthRequired,
- };
- }
- catch (OperationCanceledException)
- {
- return null;
- }
- }
- private sealed class DiscoveryResponse
- {
- public string? MessageType { get; set; }
- public string? DeviceId { get; set; }
- public string? Hostname { get; set; }
- public string? ServerVersion { get; set; }
- public string? Lan2Ip { get; set; }
- public bool AuthRequired { get; set; }
- }
- }
|