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.
588 lines
19 KiB
588 lines
19 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Mime;
|
|
using System.Threading.Tasks;
|
|
using Gtk;
|
|
using NewLife;
|
|
using NewLife.Data;
|
|
using NewLife.Log;
|
|
using NewLife.Net;
|
|
using NewLife.Reflection;
|
|
using NewLife.Threading;
|
|
using XCoder;
|
|
using XCoder.Util;
|
|
using XCoder.XNet;
|
|
#if !NET4
|
|
using TaskEx = System.Threading.Tasks.Task;
|
|
#endif
|
|
|
|
namespace XNet
|
|
{
|
|
[DisplayName("网络调试工具")]
|
|
public partial class FrmMain : Box, IXForm
|
|
{
|
|
NetServer _Server;
|
|
ISocketClient _Client;
|
|
static Task<Dictionary<String, Type>> _task;
|
|
|
|
/// <summary>业务日志输出</summary>
|
|
ILog BizLog;
|
|
|
|
#region 窗体
|
|
static FrmMain()
|
|
{
|
|
_task = Task.Factory.StartNew(() => GetNetServers());
|
|
}
|
|
|
|
public FrmMain() : base(Orientation.Horizontal, 2)
|
|
{
|
|
InitializeComponent();
|
|
|
|
//// 动态调节宽度高度,兼容高DPI
|
|
//this.FixDpi();
|
|
|
|
//Icon = IcoHelper.GetIcon("网络");
|
|
}
|
|
|
|
private void FrmMain_Load(Object sender, EventArgs e)
|
|
{
|
|
var log = TextFileLog.Create(null, "Net_{0:yyyy_MM_dd}.log");
|
|
BizLog = txtReceive.Combine(log);
|
|
txtReceive.UseWinFormControl();
|
|
|
|
//txtReceive.SetDefaultStyle(12);
|
|
//txtSend.SetDefaultStyle(12);
|
|
//numMutilSend.SetDefaultStyle(12);
|
|
|
|
//gbReceive.Tag = gbReceive.Text;
|
|
//gbSend.Tag = gbSend.Text;
|
|
|
|
_task.ContinueWith(t =>
|
|
{
|
|
var dic = EnumHelper.GetDescriptions<WorkModes>();
|
|
var list = dic.Select(kv => kv.Value).ToList();
|
|
//var ds = dic.ToDictionary(s => s.Value, s => s.Value);
|
|
foreach (var item in t.Result)
|
|
{
|
|
list.Add(item.Key);
|
|
}
|
|
//this.Invoke(() =>
|
|
//{
|
|
|
|
cbMode.AppendValues(list);
|
|
|
|
|
|
var cfg = NetConfig.Current;
|
|
if (cfg.Mode > 0 && dic.ContainsKey((WorkModes)cfg.Mode))
|
|
cbMode.Active = list.FindIndex(f => f == dic[(WorkModes)cfg.Mode]);
|
|
else
|
|
cbMode.Active = 0;
|
|
//});
|
|
});
|
|
|
|
//// 加载保存的颜色
|
|
//UIConfig.Apply(txtReceive);
|
|
|
|
LoadConfig();
|
|
|
|
//// 语音识别
|
|
//ThreadPoolX.QueueUserWorkItem(() =>
|
|
//{
|
|
// var sp = SpeechRecognition.Current;
|
|
// if (!sp.Enable) return;
|
|
|
|
// sp.Register("打开", () => this.Invoke(Connect))
|
|
// .Register("关闭", () => this.Invoke(Disconnect))
|
|
// .Register("退出", () => Application.Exit())
|
|
// .Register("发送", () => this.Invoke(() => btnSend_Click(null, null)));
|
|
|
|
// BizLog.Info("语音识别前缀:{0} 可用命令:{1}", sp.Name, sp.GetAllKeys().Join());
|
|
//});
|
|
}
|
|
#endregion
|
|
|
|
#region 加载/保存 配置
|
|
void LoadConfig()
|
|
{
|
|
var cfg = NetConfig.Current;
|
|
//mi显示应用日志.Checked = cfg.ShowLog;
|
|
//mi显示网络日志.Checked = cfg.ShowSocketLog;
|
|
//mi显示接收字符串.Checked = cfg.ShowReceiveString;
|
|
//mi显示发送数据.Checked = cfg.ShowSend;
|
|
//mi显示接收数据.Checked = cfg.ShowReceive;
|
|
//mi显示统计信息.Checked = cfg.ShowStat;
|
|
//miHexSend.Checked = cfg.HexSend;
|
|
|
|
txtSend.Buffer.Text = cfg.SendContent;
|
|
numMutilSend.Value = cfg.SendTimes;
|
|
numSleep.Value = cfg.SendSleep;
|
|
numThreads.Value = cfg.SendUsers;
|
|
//mi日志着色.Checked = cfg.ColorLog;
|
|
|
|
var ips = GetIPs().ToList();
|
|
cbLocal.AppendValues(ips);
|
|
if (!cfg.Local.IsNullOrEmpty())
|
|
cbLocal.Active = ips.FindIndex(f => f == cfg.Local);
|
|
else
|
|
cbLocal.Active = 0;
|
|
|
|
// 历史地址列表
|
|
if (!cfg.Address.IsNullOrEmpty()) cbRemote.AppendValues(cfg.Address.Split(";").ToList());
|
|
if (cfg.Port > 0) numPort.Value = cfg.Port;
|
|
}
|
|
|
|
void SaveConfig()
|
|
{
|
|
var cfg = NetConfig.Current;
|
|
//cfg.ShowLog = mi显示应用日志.Checked;
|
|
//cfg.ShowSocketLog = mi显示网络日志.Checked;
|
|
//cfg.ShowReceiveString = mi显示接收字符串.Checked;
|
|
//cfg.ShowSend = mi显示发送数据.Checked;
|
|
//cfg.ShowReceive = mi显示接收数据.Checked;
|
|
//cfg.ShowStat = mi显示统计信息.Checked;
|
|
//cfg.HexSend = miHexSend.Checked;
|
|
|
|
cfg.SendContent = txtSend.Buffer.Text;
|
|
cfg.SendTimes = (Int32)numMutilSend.Value;
|
|
cfg.SendSleep = (Int32)numSleep.Value;
|
|
cfg.SendUsers = (Int32)numThreads.Value;
|
|
//cfg.ColorLog = mi日志着色.Checked;
|
|
|
|
cfg.Local = cbLocal.GetActiveObject().ToString();
|
|
cfg.AddAddress(cbRemote.Entry.Text);
|
|
|
|
cfg.Port = (Int32)numPort.Value;
|
|
|
|
cfg.Save();
|
|
}
|
|
#endregion
|
|
|
|
#region 收发数据
|
|
void Connect()
|
|
{
|
|
_Server = null;
|
|
_Client = null;
|
|
|
|
var mode = GetMode();
|
|
var local = cbLocal.GetActiveObject().ToString();
|
|
var remote = cbRemote.Entry.Text;
|
|
var port = (Int32)numPort.Value;
|
|
|
|
var cfg = NetConfig.Current;
|
|
cfg.Mode = (Byte)mode;
|
|
|
|
switch (mode)
|
|
{
|
|
case WorkModes.UDP_TCP:
|
|
_Server = new NetServer();
|
|
break;
|
|
case WorkModes.UDP_Server:
|
|
_Server = new NetServer
|
|
{
|
|
ProtocolType = NetType.Udp
|
|
};
|
|
break;
|
|
case WorkModes.TCP_Server:
|
|
_Server = new NetServer
|
|
{
|
|
ProtocolType = NetType.Tcp
|
|
};
|
|
break;
|
|
case WorkModes.TCP_Client:
|
|
_Client = new TcpSession();
|
|
break;
|
|
case WorkModes.UDP_Client:
|
|
_Client = new UdpServer();
|
|
break;
|
|
default:
|
|
if (mode > 0)
|
|
{
|
|
var ns = GetServer(cbMode.GetActiveObject() + "");
|
|
if (ns == null) throw new XException("未识别服务[{0}]", mode);
|
|
|
|
_Server = ns.GetType().CreateInstance() as NetServer;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (_Client != null)
|
|
{
|
|
_Client.Log = cfg.ShowLog ? BizLog : Logger.Null;
|
|
if (!local.Contains("所有本地")) _Client.Local.Host = local;
|
|
_Client.Received += OnReceived;
|
|
_Client.Remote.Port = port;
|
|
_Client.Remote.Host = remote;
|
|
|
|
_Client.LogSend = cfg.ShowSend;
|
|
_Client.LogReceive = cfg.ShowReceive;
|
|
|
|
if (!_Client.Open()) return;
|
|
|
|
//"已连接服务器".SpeechTip();
|
|
}
|
|
else if (_Server != null)
|
|
{
|
|
if (_Server == null) _Server = new NetServer();
|
|
_Server.Log = cfg.ShowLog ? BizLog : Logger.Null;
|
|
_Server.SocketLog = cfg.ShowSocketLog ? BizLog : Logger.Null;
|
|
_Server.Port = port;
|
|
if (!local.Contains("所有本地")) _Server.Local.Host = local;
|
|
_Server.Received += OnReceived;
|
|
|
|
_Server.LogSend = cfg.ShowSend;
|
|
_Server.LogReceive = cfg.ShowReceive;
|
|
|
|
//// 加大会话超时时间到1天
|
|
//_Server.SessionTimeout = 24 * 3600;
|
|
|
|
_Server.Start();
|
|
|
|
//"正在监听{0}".F(port).SpeechTip();
|
|
}
|
|
|
|
//pnlSetting.Sensitive = false;
|
|
btnConnect.Label = "关闭";
|
|
|
|
cfg.Save();
|
|
|
|
_timer = new TimerX(ShowStat, null, 5000, 5000) { Async = true };
|
|
}
|
|
|
|
void Disconnect()
|
|
{
|
|
if (_Client != null)
|
|
{
|
|
_Client.Dispose();
|
|
_Client = null;
|
|
|
|
//"关闭连接".SpeechTip();
|
|
}
|
|
if (_Server != null)
|
|
{
|
|
//"停止监听{0}".F(_Server.Port).SpeechTip();
|
|
_Server.Dispose();
|
|
_Server = null;
|
|
}
|
|
if (_timer != null)
|
|
{
|
|
_timer.Dispose();
|
|
_timer = null;
|
|
}
|
|
|
|
pnlSetting.Sensitive = true;
|
|
btnConnect.Label = "打开";
|
|
}
|
|
|
|
TimerX _timer;
|
|
String _lastStat;
|
|
void ShowStat(Object state)
|
|
{
|
|
if (!NetConfig.Current.ShowStat) return;
|
|
|
|
var msg = "";
|
|
//if (_Client != null)
|
|
// msg = _Client.GetStat();
|
|
//else
|
|
if (_Server != null)
|
|
msg = _Server.GetStat();
|
|
|
|
if (!msg.IsNullOrEmpty() && msg != _lastStat)
|
|
{
|
|
_lastStat = msg;
|
|
BizLog.Info(msg);
|
|
}
|
|
}
|
|
|
|
private void btnConnect_Click(Object sender, EventArgs e)
|
|
{
|
|
SaveConfig();
|
|
|
|
var btn = sender as Button;
|
|
if (btn.Label == "打开")
|
|
Connect();
|
|
else
|
|
Disconnect();
|
|
}
|
|
|
|
void OnReceived(Object sender, ReceivedEventArgs e)
|
|
{
|
|
var session = sender as ISocketSession;
|
|
if (session == null)
|
|
{
|
|
var ns = sender as INetSession;
|
|
if (ns == null) return;
|
|
session = ns.Session;
|
|
}
|
|
|
|
if (NetConfig.Current.ShowReceiveString)
|
|
{
|
|
var line = e.Packet.ToStr();
|
|
//XTrace.WriteLine(line);
|
|
|
|
BizLog.Info(line);
|
|
}
|
|
}
|
|
|
|
Int32 _pColor = 0;
|
|
Int32 BytesOfReceived = 0;
|
|
Int32 BytesOfSent = 0;
|
|
Int32 lastReceive = 0;
|
|
Int32 lastSend = 0;
|
|
//private void timer1_Tick(Object sender, EventArgs e)
|
|
//{
|
|
// //if (!pnlSetting.Enabled)
|
|
// {
|
|
// var rcount = BytesOfReceived;
|
|
// var tcount = BytesOfSent;
|
|
// if (rcount != lastReceive)
|
|
// {
|
|
// gbReceive.Text = (gbReceive.Tag + "").Replace("0", rcount + "");
|
|
// lastReceive = rcount;
|
|
// }
|
|
// if (tcount != lastSend)
|
|
// {
|
|
// gbSend.Text = (gbSend.Tag + "").Replace("0", tcount + "");
|
|
// lastSend = tcount;
|
|
// }
|
|
|
|
// var cfg = NetConfig.Current;
|
|
// if (cfg.ColorLog) txtReceive.ColourDefault(_pColor);
|
|
// _pColor = txtReceive.TextLength;
|
|
// }
|
|
//}
|
|
|
|
private Task _Send;
|
|
private void btnSend_Click(Object sender, EventArgs e)
|
|
{
|
|
var str = txtSend.Buffer.Text;
|
|
if (String.IsNullOrEmpty(str))
|
|
{
|
|
var md = new MessageDialog(TooltipWindow,
|
|
DialogFlags.DestroyWithParent, MessageType.Warning,
|
|
ButtonsType.Close, "发送内容不能为空!");
|
|
md.Run();
|
|
md.Dispose();
|
|
//MessageBox.Show("发送内容不能为空!", MediaTypeNames.Text);
|
|
//txtSend.Focus();
|
|
return;
|
|
}
|
|
|
|
// 多次发送
|
|
var count = (Int32)numMutilSend.Value;
|
|
var sleep = (Int32)numSleep.Value;
|
|
var ths = (Int32)numThreads.Value;
|
|
if (count <= 0) count = 1;
|
|
if (sleep <= 0) sleep = 1;
|
|
|
|
SaveConfig();
|
|
|
|
var cfg = NetConfig.Current;
|
|
|
|
// 处理换行
|
|
str = str.Replace("\n", "\r\n");
|
|
var buf = cfg.HexSend ? str.ToHex() : str.GetBytes();
|
|
var pk = new Packet(buf);
|
|
|
|
if (_Client != null)
|
|
{
|
|
//if (ths <= 1)
|
|
//{
|
|
// _Client.SendMulti(pk, count, sleep);
|
|
//}
|
|
//else
|
|
{
|
|
var any = _Client.Local.Address.IsAny();
|
|
var list = new List<ISocketClient>();
|
|
for (var i = 0; i < ths; i++)
|
|
{
|
|
var client = _Client.Remote.CreateRemote();
|
|
if (!any) client.Local.EndPoint = new IPEndPoint(_Client.Local.Address, 2000 + i);
|
|
//client.StatSend = _Client.StatSend;
|
|
//client.StatReceive = _Client.StatReceive;
|
|
//client.SendMulti(buf, count, sleep);
|
|
|
|
list.Add(client);
|
|
}
|
|
var ts = new List<Task>();
|
|
for (var i = 0; i < ths; i++)
|
|
{
|
|
var task = list[i].SendConcurrency(pk, count, sleep);
|
|
ts.Add(task);
|
|
}
|
|
|
|
_Send = TaskEx.WhenAll(ts);
|
|
}
|
|
}
|
|
#if !NET4
|
|
else if (_Server != null)
|
|
{
|
|
TaskEx.Run(async () =>
|
|
{
|
|
BizLog.Info("准备向[{0}]个客户端发送[{1}]次[{2}]的数据", _Server.SessionCount, count, buf.Length);
|
|
for (var i = 0; i < count && _Server != null; i++)
|
|
{
|
|
var sw = Stopwatch.StartNew();
|
|
var cs = await _Server.SendAllAsync(buf);
|
|
sw.Stop();
|
|
BizLog.Info("{3}/{4} 已向[{0}]个客户端发送[{1}]数据 {2:n0}ms", cs, buf.Length, sw.ElapsedMilliseconds, i + 1, count);
|
|
if (sleep > 0) await TaskEx.Delay(sleep);
|
|
}
|
|
});
|
|
}
|
|
#endif
|
|
}
|
|
#endregion
|
|
|
|
#region 右键菜单
|
|
private void mi清空_Click(Object sender, EventArgs e)
|
|
{
|
|
txtReceive.Buffer.Clear();
|
|
BytesOfReceived = 0;
|
|
}
|
|
|
|
private void mi清空2_Click(Object sender, EventArgs e)
|
|
{
|
|
txtSend.Buffer.Clear();
|
|
BytesOfSent = 0;
|
|
}
|
|
|
|
//private void mi显示应用日志_Click(Object sender, EventArgs e)
|
|
//{
|
|
// var mi = sender as ToolStripMenuItem;
|
|
// mi.Checked = !mi.Checked;
|
|
//}
|
|
|
|
//private void mi显示网络日志_Click(Object sender, EventArgs e)
|
|
//{
|
|
// var mi = sender as ToolStripMenuItem;
|
|
// mi.Checked = !mi.Checked;
|
|
//}
|
|
|
|
//private void mi显示发送数据_Click(Object sender, EventArgs e)
|
|
//{
|
|
// var mi = sender as ToolStripMenuItem;
|
|
// mi.Checked = !mi.Checked;
|
|
//}
|
|
|
|
//private void mi显示接收数据_Click(Object sender, EventArgs e)
|
|
//{
|
|
// var mi = sender as ToolStripMenuItem;
|
|
// mi.Checked = !mi.Checked;
|
|
//}
|
|
|
|
//private void mi显示统计信息_Click(Object sender, EventArgs e)
|
|
//{
|
|
// var mi = sender as ToolStripMenuItem;
|
|
// NetConfig.Current.ShowStat = mi.Checked = !mi.Checked;
|
|
//}
|
|
|
|
//private void mi显示接收字符串_Click(Object sender, EventArgs e)
|
|
//{
|
|
// var mi = sender as ToolStripMenuItem;
|
|
// NetConfig.Current.ShowReceiveString = mi.Checked = !mi.Checked;
|
|
//}
|
|
|
|
//private void miHex发送_Click(Object sender, EventArgs e)
|
|
//{
|
|
// var mi = sender as ToolStripMenuItem;
|
|
// NetConfig.Current.HexSend = mi.Checked = !mi.Checked;
|
|
//}
|
|
|
|
//private void 查看Tcp参数ToolStripMenuItem_Click(Object sender, EventArgs e)
|
|
//{
|
|
// NetHelper2.ShowTcpParameters();
|
|
//}
|
|
|
|
//private void 设置最大TcpToolStripMenuItem_Click(Object sender, EventArgs e)
|
|
//{
|
|
// NetHelper2.SetTcpMax();
|
|
//}
|
|
|
|
//private void mi日志着色_Click(Object sender, EventArgs e)
|
|
//{
|
|
// var mi = sender as ToolStripMenuItem;
|
|
// mi.Checked = !mi.Checked;
|
|
//}
|
|
#endregion
|
|
|
|
private void cbMode_SelectedIndexChanged(Object sender, EventArgs e)
|
|
{
|
|
var mode = GetMode();
|
|
if (mode == 0) return;
|
|
|
|
switch (mode)
|
|
{
|
|
case WorkModes.TCP_Client:
|
|
case WorkModes.UDP_Client:
|
|
break;
|
|
default:
|
|
case WorkModes.UDP_TCP:
|
|
case WorkModes.UDP_Server:
|
|
case WorkModes.TCP_Server:
|
|
break;
|
|
case (WorkModes)0xFF:
|
|
// 端口
|
|
var ns = GetServer(cbMode.GetActiveObject().ToString());
|
|
if (ns != null && ns.Port > 0) numPort.Value = ns.Port;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
WorkModes GetMode()
|
|
{
|
|
var mode = cbMode.GetActiveObject().ToString();
|
|
if (String.IsNullOrEmpty(mode)) return 0;
|
|
|
|
var list = EnumHelper.GetDescriptions<WorkModes>().Where(kv => kv.Value == mode).ToList();
|
|
if (list.Count == 0) return (WorkModes)0xFF;
|
|
|
|
return list[0].Key;
|
|
}
|
|
|
|
static String[] GetIPs()
|
|
{
|
|
var list = NetHelper.GetIPs().Select(e => e.ToString()).ToList();
|
|
list.Insert(0, "所有本地IPv4/IPv6");
|
|
list.Insert(1, IPAddress.Any.ToString());
|
|
list.Insert(2, IPAddress.IPv6Any.ToString());
|
|
|
|
return list.ToArray();
|
|
}
|
|
|
|
static Dictionary<String, Type> _ns;
|
|
static Dictionary<String, Type> GetNetServers()
|
|
{
|
|
if (_ns != null) return _ns;
|
|
|
|
lock (typeof(FrmMain))
|
|
{
|
|
if (_ns != null) return _ns;
|
|
|
|
var dic = new Dictionary<String, Type>();
|
|
foreach (var item in typeof(NetServer).GetAllSubclasses())
|
|
{
|
|
try
|
|
{
|
|
var ns = item.CreateInstance() as NetServer;
|
|
if (ns != null) dic.Add(item.GetDisplayName() ?? ns.Name, item);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
return _ns = dic;
|
|
}
|
|
}
|
|
|
|
static NetServer GetServer(String name)
|
|
{
|
|
if (!GetNetServers().TryGetValue(name, out var t)) return null;
|
|
|
|
return t.CreateInstance() as NetServer;
|
|
}
|
|
}
|
|
}
|