|
|
@@ -23,7 +23,7 @@ using YSAI.Unility;
|
|
|
|
|
|
namespace YSAI.Netty.service
|
|
|
{
|
|
|
- public class NettyServiceOperate: IBaseAbstract, IDisposable
|
|
|
+ public class NettyServiceOperate : IBaseAbstract, IDisposable
|
|
|
{
|
|
|
protected override string TAG => "NettyServiceOperate";
|
|
|
|
|
|
@@ -105,16 +105,11 @@ namespace YSAI.Netty.service
|
|
|
/// <param name="e"></param>
|
|
|
protected void OnMe(object? sender, EventResult e)
|
|
|
{
|
|
|
+ OnEventHandler(this, e);
|
|
|
if (!e.State)
|
|
|
{
|
|
|
- //出现异常
|
|
|
- OnEventHandler(this, new EventResult(false, $"服务端异常:{e.Message}"));
|
|
|
Off();
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- OnEventHandler(this, new EventResult(true, e.Message));
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -122,6 +117,28 @@ namespace YSAI.Netty.service
|
|
|
/// </summary>
|
|
|
public class SecureChatServerHandler : SimpleChannelInboundHandler<string>
|
|
|
{
|
|
|
+ /// <summary>
|
|
|
+ /// IP处理
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="Ip"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private string IpHandle(EndPoint Ip)
|
|
|
+ {
|
|
|
+ //原始数据
|
|
|
+ string ip = string.Empty;
|
|
|
+ string? ip_od = Ip.ToString();
|
|
|
+ if (!string.IsNullOrWhiteSpace(ip_od))
|
|
|
+ {
|
|
|
+ string[] str = ip_od.Replace("[", "").Replace("]", "").Split(':');
|
|
|
+ ip = $"{str[3]}:{str[4]}";
|
|
|
+ }
|
|
|
+ return ip;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 客户端容器
|
|
|
+ /// </summary>
|
|
|
+ private static volatile ConcurrentDictionary<string, IChannel> ClientIoc = new ConcurrentDictionary<string, IChannel>();
|
|
|
/// <summary>
|
|
|
/// 消息事件
|
|
|
/// </summary>
|
|
|
@@ -152,34 +169,12 @@ namespace YSAI.Netty.service
|
|
|
if (ChannelGroup == null)
|
|
|
{
|
|
|
g = ChannelGroup = new DefaultChannelGroup(contex.Executor);
|
|
|
- MessageEvent?.Invoke(this, new EventResult(true, $"{contex.Channel.RemoteAddress} 激活了通道"));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- g.Add(contex.Channel);
|
|
|
- }
|
|
|
- public override Task DisconnectAsync(IChannelHandlerContext context)
|
|
|
- {
|
|
|
- MessageEvent?.Invoke(this, new EventResult(true, $"{context.Channel.RemoteAddress} 释放并断开连接"));
|
|
|
- return base.DisconnectAsync(context);
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 通道关闭
|
|
|
- /// </summary>
|
|
|
- /// <returns></returns>
|
|
|
- public override Task CloseAsync(IChannelHandlerContext context)
|
|
|
- {
|
|
|
- MessageEvent?.Invoke(this, new EventResult(true, $"{context.Channel.RemoteAddress} 关闭连接"));
|
|
|
- return base.CloseAsync(context);
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// 通道连接
|
|
|
- /// </summary>
|
|
|
- /// <returns></returns>
|
|
|
- public override Task ConnectAsync(IChannelHandlerContext context, EndPoint remoteAddress, EndPoint localAddress)
|
|
|
- {
|
|
|
- MessageEvent?.Invoke(this, new EventResult(true, $"{remoteAddress} 与 {localAddress} 建立连接 "));
|
|
|
- return base.ConnectAsync(context, remoteAddress, localAddress);
|
|
|
+ string ip = IpHandle(contex.Channel.RemoteAddress);
|
|
|
+ ClientIoc.AddOrUpdate(ip, contex.Channel, (k, v) => contex.Channel);
|
|
|
+ MessageEvent?.Invoke(this, new EventResult(true, $"{ip} 激活了通道",ip));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -216,8 +211,12 @@ namespace YSAI.Netty.service
|
|
|
/// <param name="e">异常信息</param>
|
|
|
public override void ExceptionCaught(IChannelHandlerContext contex, Exception ex)
|
|
|
{
|
|
|
+ //移除IP
|
|
|
+ string ip = IpHandle(contex.Channel.RemoteAddress);
|
|
|
+ ClientIoc.Remove(ip, out _);
|
|
|
+
|
|
|
//消息抛出
|
|
|
- MessageEvent?.Invoke(this, new EventResult(false, ex.Message));
|
|
|
+ MessageEvent?.Invoke(this, new EventResult(false, $"{contex.Channel.RemoteAddress} {ex.Message}", ip));
|
|
|
|
|
|
//通道关闭
|
|
|
contex.CloseAsync();
|
|
|
@@ -225,16 +224,33 @@ namespace YSAI.Netty.service
|
|
|
/// <summary>
|
|
|
/// 数据发送
|
|
|
/// </summary>
|
|
|
- /// <param name="Data"></param>
|
|
|
- public static OperateResult Send(string Data)
|
|
|
+ /// <param name="Data">数据</param>
|
|
|
+ /// <param name="IpPort">IP端口</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static OperateResult Send(string Data, string? IpPort = null)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
- if (ChannelGroup != null && ChannelGroup.Count > 0)
|
|
|
+ if (ChannelGroup != null)
|
|
|
{
|
|
|
- //群发
|
|
|
- ChannelGroup.WriteAndFlushAsync(string.Format("{0}\n", Data)).Wait();
|
|
|
- return new OperateResult(true, string.Empty, 1);
|
|
|
+ if (IpPort != null)
|
|
|
+ {
|
|
|
+ if (ClientIoc.ContainsKey(IpPort))
|
|
|
+ {
|
|
|
+ ClientIoc[IpPort].WriteAndFlushAsync(string.Format("{0}\n", Data));
|
|
|
+ return new OperateResult(true, string.Empty, 1);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return new OperateResult(false, $"{IpPort} 终端不存在", 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //群发
|
|
|
+ ChannelGroup.WriteAndFlushAsync(string.Format("{0}\n", Data));
|
|
|
+ return new OperateResult(true, string.Empty, 1);
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -273,7 +289,7 @@ namespace YSAI.Netty.service
|
|
|
{
|
|
|
if (Channel != null)
|
|
|
{
|
|
|
- return Break("On", false, "已连接");
|
|
|
+ return Break("On", false, "已启动");
|
|
|
}
|
|
|
//证书
|
|
|
X509Certificate2? Cert = null;
|
|
|
@@ -304,7 +320,8 @@ namespace YSAI.Netty.service
|
|
|
.Channel<TcpServerSocketChannel>() //创建一个通道
|
|
|
.Option(ChannelOption.SoBacklog, 128) //TCP节点布局
|
|
|
.Handler(new LoggingHandler(LogLevel.INFO)) //日志
|
|
|
- .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel => { //处理
|
|
|
+ .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
|
|
|
+ { //处理
|
|
|
IChannelPipeline pipeline = channel.Pipeline;
|
|
|
if (Cert != null)
|
|
|
{
|
|
|
@@ -345,7 +362,7 @@ namespace YSAI.Netty.service
|
|
|
{
|
|
|
if (Channel == null)
|
|
|
{
|
|
|
- return Break("Off", false, "未连接");
|
|
|
+ return Break("Off", false, "未启动");
|
|
|
}
|
|
|
Communication = null;
|
|
|
ClientGroup?.ShutdownGracefullyAsync().Wait();
|
|
|
@@ -374,18 +391,19 @@ namespace YSAI.Netty.service
|
|
|
/// 群发数据
|
|
|
/// </summary>
|
|
|
/// <param name="Data">数据</param>
|
|
|
+ /// <param name="IpPort">IP端口</param>
|
|
|
/// <returns></returns>
|
|
|
- public OperateResult Send(string Data)
|
|
|
+ public OperateResult Send(string Data, string? IpPort = null)
|
|
|
{
|
|
|
Depart("Send");
|
|
|
try
|
|
|
{
|
|
|
if (Channel == null)
|
|
|
{
|
|
|
- return Break("Send", false, "未连接");
|
|
|
+ return Break("Send", false, "未启动");
|
|
|
}
|
|
|
//等待发送完成
|
|
|
- return SecureChatServerHandler.Send(Data);
|
|
|
+ return SecureChatServerHandler.Send(Data, IpPort);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
@@ -397,10 +415,60 @@ namespace YSAI.Netty.service
|
|
|
/// 群发数据
|
|
|
/// </summary>
|
|
|
/// <param name="Data">数据</param>
|
|
|
+ /// <param name="IpPort">IP端口</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public Task<OperateResult> SendAsync(string Data, string? IpPort = null)
|
|
|
+ {
|
|
|
+ return Task.Run(() => Send(Data, IpPort));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 群发数据
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="Topic">主题</param>
|
|
|
+ /// <param name="Content">内容</param>
|
|
|
+ /// <param name="IpPort">IP端口</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public OperateResult Send(string Topic, string Content, string? IpPort = null)
|
|
|
+ {
|
|
|
+ Depart("Send");
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (Channel == null)
|
|
|
+ {
|
|
|
+ return Break("Send", false, "未启动");
|
|
|
+ }
|
|
|
+
|
|
|
+ //内部消息组织
|
|
|
+ string msg = string.Empty;
|
|
|
+ if (Content.IsJson())
|
|
|
+ {
|
|
|
+ msg = "{" + string.Format("\"T\":\"{0}\",\"C\":{1}", Topic, Content) + "}\r\n";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ msg = "{" + string.Format("\"T\":\"{0}\",\"C\":\"{1}\"", Topic, Content) + "}\r\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ //等待发送完成
|
|
|
+ return SecureChatServerHandler.Send(msg, IpPort);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return Break("Send", false, ex.Message, Exception: ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 群发数据
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="Topic">主题</param>
|
|
|
+ /// <param name="Content">内容</param>
|
|
|
+ /// <param name="IpPort">IP端口</param>
|
|
|
/// <returns></returns>
|
|
|
- public Task<OperateResult> SendAsync(string Data)
|
|
|
+ public Task<OperateResult> SendAsync(string Topic, string Content, string? IpPort = null)
|
|
|
{
|
|
|
- return Task.Run(()=> Send(Data));
|
|
|
+ return Task.Run(() => Send(Topic, Content, IpPort));
|
|
|
}
|
|
|
}
|
|
|
}
|