新生命码神工具,代码生成、网络工具、API工具、串口工具、正则工具、图标工具、加解密工具、地图接口。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
6.4 KiB

using System.ComponentModel;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization;
using NewLife;
using NewLife.Log;
using NewLife.Messaging;
using NewLife.Net;
using NewLife.Remoting;
using NewLife.Security;
using NewLife.Serialization;
using Stardust.Models;
using XCoder;
using XCoder.Common;
namespace XNet;
[Category("网络通信")]
[DisplayName("ApiServer搜索")]
public partial class FrmApiDiscover : Form, IXForm
{
private ControlConfig _config;
#region 窗体
public FrmApiDiscover()
{
InitializeComponent();
// 动态调节宽度高度,兼容高DPI
this.FixDpi();
}
private void FrmMain_Load(Object sender, EventArgs e)
{
_config = new ControlConfig { Control = this, FileName = "ApiDiscover.json" };
_config.Load();
}
#endregion
#region 核心操作
private async void btnConnect_Click(Object sender, EventArgs e)
{
_config.Save();
var btn = sender as Button;
btn.Enabled = false;
var port = (Int32)numPort.Value;
try
{
var ts = new List<Task>();
{
var ep = new IPEndPoint(IPAddress.Broadcast, port);
var task = Task.Run(() => DiscoverUdp(null, ep));
ts.Add(task);
}
foreach (var ip in NetHelper.GetIPs().Where(e => e.IsIPv4()))
{
var ep = new IPEndPoint(IPAddress.Broadcast, port);
var task = Task.Run(() => DiscoverUdp(ip, ep));
ts.Add(task);
}
//await Task.WaitAll(ts.ToArray(), 5_000);
await Task.WhenAll(ts);
}
finally
{
btn.Enabled = true;
}
}
async Task DiscoverUdp(IPAddress local, IPEndPoint ep)
{
XTrace.WriteLine("DiscoverUdp: {0} -> {1}", local, ep);
//var uri = new NetUri("udp://255.255.255.255:5500");
var client = new ApiClient($"udp://{ep.Address}:{ep.Port}");
client.Received += Client_Received;
// 异步发送,但是不等待返回,因为可能会有多个返回,在事件里处理
_ = client.InvokeAsync<Object>("Api/Info");
await Task.Delay(1_000);
//client.InvokeOneWay("Info");
//// 构建请求
//var enc = new JsonEncoder();
//var msg = enc.CreateRequest("Api/Info", null);
//var req = msg.ToPacket().ReadBytes();
//var udp = new UdpClient(ep.AddressFamily)
//{
// EnableBroadcast = true
//};
//if (local != null) udp.Client.Bind(new IPEndPoint(local, Rand.Next(1000, 60000)));
//// 发送
//udp.Send(req, req.Length, ep);
//// 多次接收
//while (true)
//{
// try
// {
// var source = new CancellationTokenSource(3_000);
// var rs = await udp.ReceiveAsync(source.Token);
// if (rs.Buffer != null)
// {
// msg = new DefaultMessage();
// msg.Read(rs.Buffer);
// if (enc.Decode(msg, out var action, out var code, out var data) && code == 0)
// {
// // 解码结果
// var result = enc.DecodeResult(action, data, msg);
// XTrace.WriteLine("Receive[{0}] {1}", udp.Client.LocalEndPoint, result.ToJson());
// if (enc.Convert(result, typeof(ApiItem)) is ApiItem ai)
// {
// ai.RemoteIP = rs.RemoteEndPoint.Address + "";
// Invoke(() => ShowItem(ai));
// }
// }
// }
// }
// catch (OperationCanceledException)
// {
// break;
// }
//}
}
private void Client_Received(Object sender, ApiReceivedEventArgs e)
{
if (e.Message == null || !e.Message.Reply) return;
var msg = e.ApiMessage;
XTrace.WriteLine("Received [{0}]: {1}", msg.Action, msg.Data.ToStr());
var client = sender as ApiClient;
var enc = client.Encoder;
// 解码结果
var result = enc.DecodeResult(msg.Action, msg.Data, e.Message, typeof(ApiItem));
//XTrace.WriteLine("Receive[{0}] {1}", udp.Client.LocalEndPoint, result.ToJson());
var remote = (e.UserState as ReceivedEventArgs)?.Remote;
if (msg.Action == "Api/Info" && enc.Convert(result, typeof(ApiItem)) is ApiItem ai)
{
ai.RemoteIP = remote.Address + "";
if (ai.Name == "StarAgent")
{
//_ = client.InvokeAsync<Object>("Info");
Task.Run(async () =>
{
var client2 = new ApiClient($"udp://{remote}");
var rs = await client2.InvokeAsync<AgentInfo>("Info");
if (rs != null)
{
ai.Code = rs.Code;
ai.Address = rs.Server;
}
});
}
if (ai.Id > 0) Invoke(() => ShowItem(ai));
}
}
#endregion
#region 显示
private IDictionary<String, ApiItem> _data;
void ShowItem(ApiItem ai)
{
_data ??= new Dictionary<String, ApiItem>();
var key = $"{ai.Name}-{ai.IP}-{ai.Id}";
if (_data.TryGetValue(key, out var old))
{
old.Time = ai.Time;
old.Code = ai.Code;
//old.Server = ai.Server;
dgv.Refresh();
}
else
{
_data.Add(key, ai);
dgv.DataSource = null;
dgv.DataSource = _data.Values.ToArray();
}
}
class ApiItem
{
public Int32 Id { get; set; }
[DataMember(Name = "Server")]
public String Name { get; set; }
[DataMember(Name = "LocalIP")]
public String IP { get; set; }
public String MachineName { get; set; }
[DataMember(Name = "FileVersion")]
public String Version { get; set; }
public String OS { get; set; }
//public String Server { get; set; }
public String RemoteIP { get; set; }
public DateTime Time { get; set; }
public String Code { get; set; }
public String Address { get; set; }
}
#endregion
}