mirror of
https://github.com/RRQM/TouchSocket.git
synced 2025-12-20 02:16:42 +08:00
优化NATService
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 默认发送
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -158,25 +158,4 @@ namespace RRQMSocket
|
||||
/// </summary>
|
||||
Disposed
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转发工作模式
|
||||
/// </summary>
|
||||
public enum NATMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 双向转发
|
||||
/// </summary>
|
||||
TwoWay,
|
||||
|
||||
/// <summary>
|
||||
/// 仅由监听地址向目标地址单向转发
|
||||
/// </summary>
|
||||
OneWay,
|
||||
|
||||
/// <summary>
|
||||
/// 仅由目标地址向监听地址单向转发
|
||||
/// </summary>
|
||||
OneWayToListen
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,更加易用。
|
||||
|
||||
API:https://www.yuque.com/eo2w71/rrqm</Description>
|
||||
<PackageProjectUrl>https://gitee.com/dotnetchina/RRQMSocket</PackageProjectUrl>
|
||||
@@ -78,7 +78,7 @@ API:https://www.yuque.com/eo2w71/rrqm</Description>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="RRQMCore" Version="8.2.0" />
|
||||
<PackageReference Include="RRQMCore" Version="8.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user