优化NATService

This commit is contained in:
若汝棋茗
2022-06-24 22:24:59 +08:00
parent 1c77691fde
commit 79ea7bfda6
11 changed files with 158 additions and 240 deletions

View File

@@ -12,6 +12,7 @@
//------------------------------------------------------------------------------
using RRQMCore;
using RRQMCore.ByteManager;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
@@ -23,60 +24,67 @@ namespace RRQMSocket
/// </summary>
public class NATService : TcpService<NATSocketClient>
{
private IPHost[] iPHosts;
private NATMode mode;
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="serviceConfig"></param>
protected override void LoadConfig(RRQMConfig serviceConfig)
/// <returns></returns>
protected override NATSocketClient GetClientInstence()
{
this.iPHosts = this.Config.GetValue<IPHost[]>(RRQMConfigExtensions.TargetIPHostsProperty);
if (this.iPHosts == null || this.iPHosts.Length == 0)
{
throw new RRQMException("目标地址未设置");
}
this.mode = this.Config.GetValue<NATMode>(RRQMConfigExtensions.NATModeProperty);
if (this.mode == NATMode.OneWayToListen)
{
serviceConfig.ReceiveType = ReceiveType.None;
}
base.LoadConfig(serviceConfig);
var client = base.GetClientInstence();
client.internalDis = this.OnTargetClientDisconnected;
client.internalTargetClientRev = this.OnTargetClientReceived;
return client;
}
/// <summary>
/// 在NAT服务器收到数据时。
/// </summary>
/// <param name="socketClient"></param>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
/// <returns>需要转发的数据。</returns>
protected virtual byte[] OnNATReceived(NATSocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{
return byteBlock.ToArray();
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="socketClient"></param>
/// <param name="e"></param>
protected sealed override void OnConnecting(NATSocketClient socketClient, ClientOperationEventArgs e)
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
protected sealed override void OnReceived(NATSocketClient socketClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{
List<Socket> sockets = new List<Socket>();
foreach (var iPHost in this.iPHosts)
var data = this.OnNATReceived(socketClient, byteBlock, requestInfo);
if (data != null)
{
try
{
Socket socket = new Socket(iPHost.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(iPHost.EndPoint);
sockets.Add(socket);
}
catch (Exception ex)
{
this.Logger.Debug(RRQMCore.Log.LogType.Error, this, ex.Message, ex);
}
}
if (sockets.Count == 0)
{
this.Logger.Debug(RRQMCore.Log.LogType.Error, this, "转发地址均无法建立,已拒绝本次连接。", null);
e.RemoveOperation(Operation.Permit);
return;
socketClient.SendToTargetClient(data, 0, data.Length);
}
}
socketClient.BeginRunTargetSocket(this.mode, sockets.ToArray());
/// <summary>
/// 当目标客户端断开。
/// </summary>
/// <param name="socketClient"></param>
/// <param name="tcpClient"></param>
/// <param name="e"></param>
protected virtual void OnTargetClientDisconnected(NATSocketClient socketClient, ITcpClient tcpClient, ClientDisconnectedEventArgs e)
{
base.OnConnecting(socketClient, e);
}
/// <summary>
/// 在目标客户端收到数据时。
/// </summary>
/// <param name="socketClient"></param>
/// <param name="tcpClient"></param>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
/// <returns></returns>
protected virtual byte[] OnTargetClientReceived(NATSocketClient socketClient, ITcpClient tcpClient, ByteBlock byteBlock, IRequestInfo requestInfo)
{
return byteBlock.ToArray();
}
}
}

View File

@@ -10,10 +10,12 @@
// 感谢您的下载和使用
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore;
using RRQMCore.ByteManager;
using RRQMCore.Log;
using System;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace RRQMSocket
{
@@ -22,99 +24,119 @@ namespace RRQMSocket
/// </summary>
public class NATSocketClient : SocketClient
{
private readonly System.Threading.ReaderWriterLockSlim m_lockSlim = new System.Threading.ReaderWriterLockSlim();
private readonly List<ITcpClient> m_targetClients;
internal Action<NATSocketClient, ITcpClient, ClientDisconnectedEventArgs> internalDis;
internal Func<NATSocketClient, ITcpClient, ByteBlock, IRequestInfo, byte[]> internalTargetClientRev;
/// <summary>
/// <inheritdoc/>
/// 获取所有目标客户端
/// </summary>
public sealed override bool CanSetDataHandlingAdapter => false;
/// <returns></returns>
public ITcpClient[] GetTargetClients()
{
return this.m_targetClients.ToArray();
}
/// <summary>
/// 构造函数
/// </summary>
public NATSocketClient()
{
this.SetAdapter(new NormalDataHandlingAdapter());
}
private Socket[] targetSockets;
internal void BeginRunTargetSocket(NATMode mode, Socket[] sockets)
{
this.targetSockets = sockets;
if (mode == NATMode.OneWay)
{
return;
}
foreach (var socket in sockets)
{
SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
eventArgs.Completed += this.EventArgs_Completed;
ByteBlock byteBlock = BytePool.GetByteBlock(this.BufferLength);
eventArgs.UserToken = new NATModel(socket, byteBlock);
eventArgs.SetBuffer(byteBlock.Buffer, 0, byteBlock.Buffer.Length);
if (!socket.ReceiveAsync(eventArgs))
{
this.ProcessReceived(eventArgs);
}
}
}
private void EventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
try
{
this.ProcessReceived(e);
}
catch (Exception ex)
{
this.Close(ex.Message);
}
}
private void ProcessReceived(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success && e.BytesTransferred > 0)
{
NATModel model = (NATModel)e.UserToken;
ByteBlock byteBlock = model.ByteBlock;
byteBlock.SetLength(e.BytesTransferred);
this.HandleReceivedDataFromTarget(byteBlock);
try
{
ByteBlock newByteBlock = BytePool.GetByteBlock(this.BufferLength);
model.ByteBlock = newByteBlock;
e.SetBuffer(newByteBlock.Buffer, 0, newByteBlock.Buffer.Length);
if (!model.Socket.ReceiveAsync(e))
{
this.ProcessReceived(e);
}
}
catch (Exception ex)
{
this.Close(ex.Message);
}
}
else
{
this.Close("远程终端主动断开");
}
this.m_targetClients = new List<ITcpClient>();
}
/// <summary>
/// 处理从目标服务器接收的数据
/// 添加转发客户端
/// </summary>
/// <param name="byteBlock"></param>
protected virtual void HandleReceivedDataFromTarget(ByteBlock byteBlock)
/// <param name="config"></param>
/// <returns></returns>
public ITcpClient AddTargetClient(RRQMConfig config)
{
using WriteLock writeLock = new WriteLock(this.m_lockSlim);
TcpClient tcpClient = new TcpClient();
tcpClient.Disconnected += this.TcpClient_Disconnected;
tcpClient.Received += this.TcpClient_Received;
tcpClient.Setup(config);
tcpClient.Connect();
this.m_targetClients.Add(tcpClient);
return tcpClient;
}
/// <summary>
/// 添加转发客户端。
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public Task<ITcpClient> AddTargetClientAsync(RRQMConfig config)
{
return Task.Run(() =>
{
return this.AddTargetClient(config);
});
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (this.m_targetClients != null)
{
foreach (var socket in this.m_targetClients)
{
socket.SafeDispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// 发送数据到全部转发端。
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
public void SendToTargetClient(byte[] buffer, int offset, int length)
{
using WriteLock writeLock = new WriteLock(this.m_lockSlim);
foreach (var socket in this.m_targetClients)
{
try
{
socket.Send(buffer, offset, length);
}
catch
{
}
}
}
private void TcpClient_Disconnected(ITcpClientBase client, ClientDisconnectedEventArgs e)
{
using WriteLock writeLock = new WriteLock(this.m_lockSlim);
this.m_targetClients.Remove((ITcpClient)client);
this.internalDis?.Invoke(this, (ITcpClient)client, e);
}
private void TcpClient_Received(TcpClient client, ByteBlock byteBlock, IRequestInfo requestInfo)
{
if (this.disposedValue)
{
return;
}
try
{
this.Send(byteBlock);
var data = this.internalTargetClientRev?.Invoke(this, client, byteBlock, requestInfo);
if (data != null)
{
this.Send(data);
}
}
catch (Exception ex)
{
@@ -125,45 +147,5 @@ namespace RRQMSocket
byteBlock.Dispose();
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="byteBlock"></param>
/// <param name="requestInfo"></param>
protected override void HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
if (this.disposedValue || this.targetSockets == null)
{
return;
}
foreach (var socket in this.targetSockets)
{
try
{
socket.Send(byteBlock.Buffer, 0, byteBlock.Len, SocketFlags.None);
}
catch
{
}
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (this.targetSockets != null)
{
foreach (var socket in this.targetSockets)
{
socket.Dispose();
}
}
base.Dispose(disposing);
}
}
}

View File

@@ -282,14 +282,14 @@ namespace RRQMSocket
}
/// <summary>
/// 处理已接收到的数据。如果覆盖父类方法,则不会触发服务器方法。
/// 处理已接收到的数据。
/// <para>根据不同的数据处理适配器,会传递不同的数据</para>
/// </summary>
/// <param name="byteBlock">以二进制流形式传递</param>
/// <param name="requestInfo">以解析的数据对象传递</param>
protected virtual void HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
{
this.m_service.OnInternalReceivedData(this, byteBlock, requestInfo);
}
/// <summary>
@@ -663,6 +663,7 @@ namespace RRQMSocket
{
return;
}
if (this.m_usePlugin)
{
ReceivedDataEventArgs args = new ReceivedDataEventArgs(byteBlock, requestInfo);
@@ -672,7 +673,10 @@ namespace RRQMSocket
return;
}
}
this.HandleReceivedData(byteBlock, requestInfo);
this.m_service.OnInternalReceivedData(this, byteBlock, requestInfo);
}
#region

View File

@@ -362,10 +362,6 @@ namespace RRQMSocket
/// <exception cref="ArgumentNullException"></exception>
public void AddPlugin(IPlugin plugin)
{
if (plugin.Logger == default)
{
plugin.Logger = this.Container.Resolve<ILog>();
}
this.PluginsManager.Add(plugin);
}

View File

@@ -235,7 +235,7 @@ namespace RRQMSocket
}
/// <summary>
/// 当收到适配器数据,父类方法为空
/// 当收到适配器数据。
/// </summary>
/// <param name="socketClient"></param>
/// <param name="byteBlock"></param>
@@ -276,10 +276,6 @@ namespace RRQMSocket
throw new ArgumentNullException(nameof(this.Config), "请在SetUp后添加插件。");
}
if (plugin.Logger == default)
{
plugin.Logger = this.Container.Resolve<ILog>();
}
this.PluginsManager.Add(plugin);
}

View File

@@ -311,10 +311,6 @@ namespace RRQMSocket
{
throw new ArgumentNullException(nameof(this.Config), "请在SetUp后添加插件。");
}
if (plugin.Logger == default)
{
plugin.Logger = this.Container.Resolve<ILog>();
}
this.PluginsManager.Add(plugin);
}

View File

@@ -25,46 +25,6 @@ namespace RRQMSocket
{
#region NAT
/// <summary>
/// 转发的类型,
/// 所需类型<see cref="RRQMSocket.NATMode"/>
/// </summary>
public static readonly DependencyProperty NATModeProperty =
DependencyProperty.Register("NATMode", typeof(NATMode), typeof(RRQMConfigExtensions), NATMode.TwoWay);
/// <summary>
/// 转发的目标地址集合,
/// 所需类型<see cref="IPHost"/>数组
/// </summary>
public static readonly DependencyProperty TargetIPHostsProperty =
DependencyProperty.Register("TargetIPHosts", typeof(IPHost[]), typeof(RRQMConfigExtensions), null);
/// <summary>
/// 转发的类型
/// <para>仅适用于<see cref="NATService"/>及派生类</para>
/// </summary>
/// <param name="config"></param>
/// <param name="value"></param>
/// <returns></returns>
public static RRQMConfig SetNATMode(this RRQMConfig config, NATMode value)
{
config.SetValue(NATModeProperty, value);
return config;
}
/// <summary>
/// 转发的目标地址集合。
/// <para>仅适用于<see cref="NATService"/>及派生类</para>
/// </summary>
/// <param name="config"></param>
/// <param name="value"></param>
/// <returns></returns>
public static RRQMConfig SetTargetIPHosts(this RRQMConfig config, IPHost[] value)
{
config.SetValue(TargetIPHostsProperty, value);
return config;
}
#endregion NAT
#region ServiceBase

View File

@@ -158,25 +158,4 @@ namespace RRQMSocket
/// </summary>
Disposed
}
/// <summary>
/// 转发工作模式
/// </summary>
public enum NATMode
{
/// <summary>
/// 双向转发
/// </summary>
TwoWay,
/// <summary>
/// 仅由监听地址向目标地址单向转发
/// </summary>
OneWay,
/// <summary>
/// 仅由目标地址向监听地址单向转发
/// </summary>
OneWayToListen
}
}

View File

@@ -28,12 +28,6 @@ namespace RRQMSocket
/// </summary>
int Order { get; set; }
/// <summary>
/// 日志记录器。
/// <para>在<see cref="IPluginsManager.Add(IPlugin)"/>之前如果没有赋值的话,随后会用<see cref="IContainer.Register(DependencyDescriptor, string)"/>填值</para>
/// </summary>
ILog Logger { get; set; }
/// <summary>
/// 包含此插件的插件管理器
/// </summary>

View File

@@ -11,6 +11,7 @@
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
using RRQMCore;
using RRQMCore.Dependency;
using RRQMCore.Log;
namespace RRQMSocket.Plugins
@@ -18,11 +19,12 @@ namespace RRQMSocket.Plugins
/// <summary>
/// 插件实现基类
/// </summary>
public class TcpPluginBase : DisposableObject, ITcpPlugin
public abstract class TcpPluginBase : DisposableObject, ITcpPlugin
{
/// <summary>
/// <inheritdoc/>
/// </summary>
[DependencyInject()]
public ILog Logger { get; set; }
/// <summary>
@@ -34,6 +36,7 @@ namespace RRQMSocket.Plugins
/// <inheritdoc/>
/// </summary>
public IPluginsManager PluginsManager { get; set; }
void ITcpPlugin.OnConnecting(ITcpClientBase client, ClientOperationEventArgs e)
{
this.OnConnecting(client, e);

View File

@@ -4,7 +4,7 @@
<ApplicationIcon>RRQM.ico</ApplicationIcon>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>RRQM.pfx</AssemblyOriginatorKeyFile>
<Version>8.2.0</Version>
<Version>8.2.1</Version>
<LangVersion>8.0</LangVersion>
<Company>若汝棋茗</Company>
<Copyright>Copyright © 2022 若汝棋茗</Copyright>
@@ -12,7 +12,7 @@
<Description>介绍RRQMSocket是一个整合性的、超轻量级的、支持插件的网络通信框架。包含了TCP、UDP、Ssl等一系列的通信模块。更加的灵活、便捷。让使用者能够更加简单的、快速的搭建网络框架。
更新说明:
无其他更新
优化NATService更加易用
APIhttps://www.yuque.com/eo2w71/rrqm</Description>
<PackageProjectUrl>https://gitee.com/dotnetchina/RRQMSocket</PackageProjectUrl>
@@ -78,7 +78,7 @@ APIhttps://www.yuque.com/eo2w71/rrqm</Description>
</ItemGroup>
<ItemGroup>
<PackageReference Include="RRQMCore" Version="8.2.0" />
<PackageReference Include="RRQMCore" Version="8.2.1" />
</ItemGroup>
</Project>