/**
*┌──────────────────────────────────────────────────────────────┐
*│ 描 述:HPSocket的TCPServer、TCPClient通讯相关的工具类(类库提供的方法、属性学习)
*│ 作 者:执笔小白
*│ 版 本:1.0
*│ 创建时间:2023-6-13 10:40:56
*└──────────────────────────────────────────────────────────────┘
*┌──────────────────────────────────────────────────────────────┐
*│ 命名空间: ZhibiXiaobai
*│ 类 名:HPSocket_TCPServerHelper、HPSocket_TcpClientHelper
*└──────────────────────────────────────────────────────────────┘
*/
using HPSocket;
using HPSocket.Tcp;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
namespace csharp_networkprotocol_hpsocket
{
///
/// HPSocket_TCPServer示例帮助类(类库提供的方法、属性学习)
/// System.Net.Sockets类库
/// TcpServer
///
public class HPSocket_TCPServerHelper
{
#region 接收端(服务端)
///
/// 侦听来自 TCP 网络客户端的连接
///
public ITcpServer _server = null;
#region 创建时的设置项
///
/// 要绑定的服务器地址
///
public string Address
{
get { return _server.Address; }
set { _server.Address = value; }
}
///
/// 要绑定的服务器端口
///
public ushort Port
{
get
{
return _server.Port;
}
set { _server.Port = value; }
}
///
/// 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大)
///
public uint MaxConnectionCount
{
get
{
return _server.MaxConnectionCount;
}
set { _server.MaxConnectionCount = value; }
}
///
/// 读取或设置是否标记静默时间
/// (设置为 true 时 DisconnectSilenceConnections() 和 GetSilencePeriod()才有效,默认:false)
///
public bool IsMarkSilence
{
get { return _server.IsMarkSilence; }
set { _server.IsMarkSilence = value; }
}
///
/// 获取或设置数据发送策略
///
public SendPolicy SendPolicy
{
get {return _server.SendPolicy; }
set { _server.SendPolicy = value; }
}
///
/// 获取或设置 OnSend 事件同步策略
///
public OnSendSyncPolicy OnSendSyncPolicy
{
get
{
return _server.OnSendSyncPolicy;
}
set { _server.OnSendSyncPolicy = value; }
}
///
/// 获取或设置地址重用选项
///
public ReuseAddressPolicy ReuseAddressPolicy
{
get {return _server.ReuseAddressPolicy; }
set { _server.ReuseAddressPolicy = value; }
}
///
/// 获取或设置是否开启 nodelay 模式 (默认: false, 不开启)
///
public bool NoDelay
{
get {return _server.NoDelay; }
set { _server.NoDelay = value; }
}
#region 心跳检测
///
/// 读取或设置心跳包间隔(毫秒,0 则不发送心跳包)
///
public uint KeepAliveTime
{
get {return _server.KeepAliveTime; }
set { _server.KeepAliveTime = value;
}
}
///
/// 读取或设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线)
///
public uint KeepAliveInterval
{
get
{
return _server.KeepAliveInterval;
}
set { _server.KeepAliveInterval = value; }
}
#endregion 心跳检测
#region 性能优化
///
/// 读取或设置 Accept 预投递数量(根据负载调整设置,Accept 预投递数量越大则支持的并发连接请求越多)
///
public uint AcceptSocketCount
{
get { return _server.AcceptSocketCount; }
set { _server.AcceptSocketCount = value; }
}
///
/// 读取或设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数)
///
public uint SocketBufferSize
{
get
{
return _server.SocketBufferSize;
}
set { _server.SocketBufferSize = value; }
}
///
/// 读取或设置监听 Socket 的等候队列大小(根据并发连接数量调整设置)
///
public uint SocketListenQueue
{
get { return _server.SocketListenQueue; }
set { _server.SocketListenQueue = value; }
}
///
/// 读取或设置工作线程数量(通常设置为 2 * CPU + 2)
///
public uint WorkerThreadCount
{
get { return _server.WorkerThreadCount; }
set { _server.WorkerThreadCount = value; }
}
///
/// 读取或设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用)
///
public uint FreeSocketObjLockTime
{
get { return _server.FreeSocketObjLockTime; }
set { _server.FreeSocketObjLockTime = value; }
}
///
/// 读取或设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2)
///
public uint FreeSocketObjPool
{
get { return _server.FreeSocketObjPool; }
set { _server.FreeSocketObjPool = value; }
}
///
/// 读取或设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍)
///
public uint FreeBufferObjPool
{
get { return _server.FreeBufferObjPool; }
set { _server.FreeBufferObjPool = value; }
}
///
/// 读取或设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍)
///
public uint FreeSocketObjHold
{
get { return _server.FreeSocketObjHold; }
set { _server.FreeSocketObjHold = value; }
}
///
/// 读取或设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍)
///
public uint FreeBufferObjHold
{
get { return _server.FreeBufferObjHold; }
set { _server.FreeBufferObjHold = value; }
}
#endregion 性能优化
#endregion 创建时的设置项
#region 常用属性
///
/// 获取是否启动
///
public bool HasStarted => _server.HasStarted;
///
/// 获取状态
///
public ServiceState State => _server.State;
///
/// 获取连接数
///
public uint ConnectionCount => _server.ConnectionCount;
///
/// 是否为安全连接(SSL/HTTPS)
///
public bool IsSecure => _server.IsSecure;
#endregion 常用属性
#region 常用方法
///
/// 启动服务
///
///
public bool Start() => _server.Start();
///
/// 停止服务
///
///
public bool Stop() => _server.Stop();
#region 附加信息
///
/// 获取所有附加数据
///
///
public ConcurrentDictionary GetAllExtra() => _server.GetAllExtra();
///
/// 获取附加数据
///
///
///
///
public T GetExtra(IntPtr connId) => _server.GetExtra(connId);
///
/// 获取连接附加数据, 非托管版本, hp-socket自带方法;非特殊需求不要使用这个方法, 请直接使用 GetExtra();
///
///
///
///
public bool NativeGetConnectionExtra(IntPtr connId, out IntPtr extra) => _server.NativeGetConnectionExtra(connId, out extra);
///
/// 设置附加数据
///
///
///
///
public bool SetExtra(IntPtr connId, object obj) => _server.SetExtra(connId, obj);
///
/// 设置连接附加数据, 非托管版本, hp-socket自带方法;非特殊需求不要使用这个方法, 请直接使用 SetExtra();
///
///
///
///
public bool NativeSetConnectionExtra(IntPtr connId, IntPtr extra) => _server.NativeSetConnectionExtra(connId, extra);
///
/// 删除附加数据
///
///
///
public bool RemoveExtra(IntPtr connId) => _server.RemoveExtra(connId);
#endregion 附加信息
#region 发送数据
///
/// 发送数据
///
/// 连接id
/// 数据源
/// 数据长度
///
public bool Send(IntPtr connId, byte[] bytes, int length) => _server.Send(connId, bytes, length);
///
/// 发送数据-指针偏移
///
///
///
/// 对bytes的偏移
/// 发多大
///
public bool Send(IntPtr connId, byte[] bytes, int offset, int length) => _server.Send(connId, bytes, offset, length);
///
/// 发送多组数据 向指定连接发送多组数据 TCP - 顺序发送所有数据包
///
/// 连接 ID
/// 发送缓冲区数组
/// true.成功,false.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendPackets(IntPtr connId, Wsabuf[] buffers) => SendPackets(connId, buffers);
#endregion 发送数据
#region 发送本地小文件
///
/// 发送本地小文件
/// 向指定连接发送 4096 KB 以下的小文件
///
///
/// 文件路径
/// 头部附加数据
/// 尾部附加数据
/// true.成功,false.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendSmallFile(IntPtr connId, string filePath, ref Wsabuf head, ref Wsabuf tail) => _server.SendSmallFile(connId, filePath, ref head, ref tail);
///
/// 发送本地小文件
/// 向指定连接发送 4096 KB 以下的小文件
///
///
/// 文件路径
/// 头部附加数据,可以为null
/// 尾部附加数据,可以为null
/// true.成功,false.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendSmallFile(IntPtr connId, string filePath, byte[] head, byte[] tail) => _server.SendSmallFile(connId, filePath, head, tail);
#endregion 发送本地小文件
#region 查询服务器信息
///
/// 获取监听socket的地址信息
///
///
///
///
public bool GetListenAddress(out string ip, out ushort port) => _server.GetListenAddress(out ip, out port);
#endregion 查询服务器信息
#region 查询客户端信息
///
/// 获取所有连接
///
///
public List GetAllConnectionIds() => _server.GetAllConnectionIds();
///
/// 获取某客户端连接是否有效
///
///
///
public bool IsConnected(IntPtr connId) => _server.IsConnected(connId);
///
/// 获取某客户端连接的接收状态
///
///
///
public ReceiveState GetReceiveState(IntPtr connId) => _server.GetReceiveState(connId);
///
/// 获取某个连接的本地地址信息
///
///
///
///
///
public bool GetLocalAddress(IntPtr connId, out string ip, out ushort port) => _server.GetLocalAddress(connId, out ip, out port);
///
/// 获取某个连接的远程地址信息
///
///
///
///
///
public bool GetRemoteAddress(IntPtr connId, out string ip, out ushort port) => _server.GetRemoteAddress(connId, out ip, out port);
///
/// 获取指定连接的连接时长(毫秒)
///
///
///
///
public bool GetConnectPeriod(IntPtr connId, out uint period) => _server.GetConnectPeriod(connId, out period);
///
/// 获取某个连接静默时间(毫秒)
///
///
///
///
public bool GetSilencePeriod(IntPtr connId, out uint period) => _server.GetSilencePeriod(connId, out period);
///
/// 获取连接中未发出数据的长度
///
///
///
///
public bool GetPendingDataLength(IntPtr connId, out int length) => _server.GetPendingDataLength(connId, out length);
#endregion 查询客户端信息
#region 断开与客户端的连接
///
/// 断开与某个客户的连接
///
///
/// 是否强制断开
///
public bool Disconnect(IntPtr connId, bool force = true) => _server.Disconnect(connId, force);
///
/// 断开超过指定时间的连接
///
/// 毫秒
/// 强制
///
public bool DisconnectLongConnections(uint period, bool force = true) => _server.DisconnectLongConnections(period, force);
///
/// 断开超过指定时长的静默连接
///
/// 毫秒
/// 强制
///
public bool DisconnectSilenceConnections(uint period, bool force = true) => _server.DisconnectSilenceConnections(period, force);
#endregion 断开与客户端的连接
#region 暂停/唤醒接收某客户端
///
/// 暂停接收
///
///
///
public bool PauseReceive(IntPtr connId) => _server.PauseReceive(connId);
///
/// 唤醒接收
///
///
///
public bool ResumeReceive(IntPtr connId) => _server.ResumeReceive(connId);
#endregion 暂停/唤醒接收某客户端
#endregion 常用方法
#region 创建侦听的方法与示例方法(后使用Start()开启侦听)
///
/// 创建侦听
///
/// 地址
/// 端口
///
public ITcpServer CreateTcpServer()
{
_server = new TcpServer();
return _server;
}
///
/// 创建TCP侦听 -示例
///
/// 地址
/// 端口
///
public ITcpServer CreateTcpServerDemo(IPAddress localAddr, int port)
{
// <1> 创建服务器对象
_server = new TcpServer();
// <2> 设置socket接收长度
_server.SocketBufferSize = 4096; // 4K
_server.Address = "192.168.10.11";
_server.Port = 8085;
// <3> 绑定事件
//event ServerAcceptEventHandler OnAccept; // TCP连接准备事件
//event ServerHandShakeEventHandler OnHandShake; // TCP握手成功事件
//event ServerPrepareListenEventHandler OnPrepareListen; // 监听事件
//event ServerSendEventHandler OnSend; // 数据包发送事件
//event ServerReceiveEventHandler OnReceive; // 数据包到达事件
//event ServerCloseEventHandler OnClose; // TCP连接关闭事件
//event ServerShutdownEventHandler OnShutdown; // TCP服务器关闭事件
_server.OnAccept += OnAccept; // TCP连接准备事件-使用附加数据处理黏包
_server.OnHandShake += OnHandShake; // TCP握手成功事件
_server.OnPrepareListen += OnPrepareListen; // 监听事件
_server.OnSend += OnSend; // 数据包发送事件
_server.OnReceive += OnReceive; // 数据包接收事件
_server.OnClose += OnClose; // TCP连接关闭事件
_server.OnShutdown += OnShutdown; // TCP服务器关闭事件
return _server;
}
#region TCP事件
///
/// TCP连接事件(连接前)-使用附加数据处理黏包,不可异步
///
/// 服务器对象
/// 连接ID
/// 如果为 TCP 连接,pClient为 SOCKET 句柄;如果为 UDP 连接,pClient为 SOCKADDR 指针;
///
private HandleResult OnAccept(IServer sender, IntPtr connId, IntPtr client)
{
// 获取客户端地址
string ip = string.Empty;
ushort port = 0;
if (!sender.GetRemoteAddress(connId, out ip, out port))
{
return HandleResult.Error;
}
// 设置附加数据(用来做粘包处理)
sender.SetExtra(connId, string.Empty); // 初始化附加信息
//ShowLog(string.Format("TCP客户端接入({0}), ip: {1}, port: {2}", connId, ip, port));
return HandleResult.Ok;
}
///
/// TCP握手成功事件
///
/// 服务器对象
/// 连接ID
///
private HandleResult OnHandShake(IServer sender, IntPtr connId)
{
// 一般用不到
return HandleResult.Ok;
}
///
/// 监听事件
///
/// 服务器对象
/// 连接ID
///
private HandleResult OnPrepareListen(IServer server, IntPtr intPtr)
{
//ShowLog(string.Format("TCP服务器开启监听({0}:{1}), listen:{2}", server.Address, server.Port, intPtr));
return HandleResult.Ok;
}
///
/// 数据包发送事件
///
/// 服务器对象
/// 连接ID
/// 数据包
///
private HandleResult OnSend(IServer sender, IntPtr connId, byte[] data)
{
string ip = string.Empty;
ushort port = 0;
sender.GetRemoteAddress(connId, out ip, out port); // 获取客户端地址
//ShowLog(string.Format("TCP服务器发送数据[ID:{0},客户端地址:‘{1}:{2}’];数据[长度{3}]:{4}", connId, ip ?? "未找到IP", port, data.Length, Encoding.ASCII.GetString(data)));
return HandleResult.Ok;
}
///
/// 数据包接收事件
///
/// 服务器对象
/// 连接ID
/// 数据包
///
private HandleResult OnReceive(IServer sender, IntPtr connId, byte[] data)
{
// <1> 获取客户端地址
string ip = string.Empty;
ushort port = 0;
if (!sender.GetRemoteAddress(connId, out ip, out port))
{
return HandleResult.Error;
}
// <2> 获取附加数据对象
var extraDataStr = sender.GetExtra(connId);
if (extraDataStr == null)
{
return HandleResult.Error;
}
// <3> 将接收数据转换成字符串
string msg = Encoding.ASCII.GetString(data);
extraDataStr += msg; // 添加数据到缓存_不合格的数据添加到缓存区(用于粘包、拆包)
// <4> 显示信息
//ShowLog(string.Format("TCP服务器接收客户端[ID:{0},IP:‘{1}:{2}’]的信息;数据:[长度{3}]: {4}", connId, ip, port, data.Length, msg));
// <5> 处理数据
HandleResult result;
string _endsWith = "\r\n"; // TCP包的数据结束符
while (true)
{
int index = extraDataStr.IndexOf(_endsWith);
if (index == -1) // 数据接收不完整,忽略后等待下一次接收
{
result = HandleResult.Ignore;
break;
}
else
{
string validMsg = extraDataStr.Remove(0, index);
// <6> 业务处理-异步(validMsg内容解析时的格式校验属于业务范畴)
// <7> 移除已取出数据
extraDataStr = extraDataStr.Remove(0, index + _endsWith.Length);
}
}
// <8> 保存PacketData数据
if (extraDataStr.Length > _server.SocketBufferSize) // 可选-控制长度为4096(注:实际所占控件大小>4096)
{
int length_Delete = extraDataStr.Length - Convert.ToInt32(_server.SocketBufferSize);
extraDataStr = extraDataStr.Remove(0, length_Delete); // 清除长度超标数据
}
sender.SetExtra(connId, extraDataStr); // 初始化附加信息
return result;
}
///
/// TCP连接关闭事件
///
/// 服务器对象
/// 连接ID
/// 关闭的类型
/// 错误时的错误代码
///
private HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation socketOperation, int errorCode)
{
// <1> 获取客户端地址
string ip = string.Empty;
ushort port = 0;
if (!sender.GetRemoteAddress(connId, out ip, out port))
{
return HandleResult.Ignore;
}
// <2> 释放附加数据
if (sender.GetExtra(connId) != null)
{
sender.RemoveExtra(connId); // 删除附加数据
}
// <3> 显示信息
//ShowLog(string.Format("TCP客户端连接断开(ID {0},地址 {1}:{2}), 断开类型: {3},错误代码: {4}", connId, ip, port, socketOperation.ToString(), errorCode));
return HandleResult.Ok;
}
///
/// TCP服务器关闭事件
///
/// 服务器对象
///
private HandleResult OnShutdown(IServer sender)
{
//ShowLog(string.Format("TCP服务器关闭({0}:{1})", sender.Address, sender.Port));
return HandleResult.Ok;
}
#endregion TCP事件
#endregion 创建侦听的方法与示例方法(后使用Start()开启侦听)
#endregion 接收端(服务端)
}
///
/// HPSocket_TcpClient示例帮助类(示例学习)
/// System.Net.Sockets类库
/// TcpClient
///
public class HPSocket_TcpClientHelper
{
#region 发送端(客户端)
///
/// TCP客户端
///
public ITcpClient _client = new TcpClient();
///
/// 本地绑定到哪个ip
///
public string BindAddress
{
get { return _client.BindAddress; }
set { _client.BindAddress = value; }
}
///
/// 本地绑定到哪个端口
///
public ushort BindPort
{
get { return _client.BindPort; }
set { _client.BindPort = value; }
}
///
/// 远程服务器地址
///
public string Address
{
get { return _client.Address; }
set { _client.Address = value; }
}
///
/// 远程服务器端口
///
public ushort Port
{
get { return _client.Port; }
set { _client.Port = value; }
}
#region 创建时的设置项
///
/// 是否异步连接,默认为真
///
public bool Async
{
get { return _client.Async; }
set { _client.Async = value; }
}
///
/// 读取或设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj))
///
public uint SocketBufferSize
{
get { return _client.SocketBufferSize; }
set { _client.SocketBufferSize = value; }
}
///
/// 连接超时时间, 默认操作系统默认值
/// 单位: 毫秒
/// 异常:T:System.InvalidOperationException:同步连接、.NET Framework2.0以及设置小于100毫秒会引发此异常
///
public int ConnectionTimeout
{
get { return _client.ConnectionTimeout; }
set { _client.ConnectionTimeout = value; }
}
///
/// 附加数据
/// 赋值:client.ExtraData = myObj;
/// 取值:var data = ExtraData as MyData;
///
public object ExtraData
{
get { return _client.ExtraData; }
set { _client.ExtraData = value; }
}
///
/// 获取或设置是否开启 nodelay 模式 (默认: false, 不开启)
///
public bool NoDelay
{
get { return _client.NoDelay; }
set { _client.NoDelay = value; }
}
#region 心跳
///
/// 读取或设置心跳包间隔(毫秒,0 则不发送心跳包)
///
public uint KeepAliveTime
{
get { return _client.KeepAliveTime; }
set { _client.KeepAliveTime = value; }
}
///
/// 读取或设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线)
///
public uint KeepAliveInterval
{
get { return _client.KeepAliveInterval; }
set { _client.KeepAliveInterval = value; }
}
#endregion 心跳
///
/// 获取或设置暂停接收状态,设置状态时,不允许设置为ReceiveState.Unknown,
///
public ReceiveState PauseReceive
{
get { return _client.PauseReceive; }
set { _client.PauseReceive = value; }
}
///
/// 获取或设置地址重用选项
///
public ReuseAddressPolicy ReuseAddressPolicy
{
get { return _client.ReuseAddressPolicy; }
set { _client.ReuseAddressPolicy = value; }
}
///
/// 代理列表
///
public List ProxyList
{
get { return _client.ProxyList; }
set { _client.ProxyList = value; }
}
#region 性能优化
///
/// 读取或设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 )
///
public uint FreeBufferPoolSize
{
get { return _client.FreeBufferPoolSize; }
set { _client.FreeBufferPoolSize = value; }
}
///
/// 读取或设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍)
///
public uint FreeBufferPoolHold
{
get { return _client.FreeBufferPoolHold; }
set { _client.FreeBufferPoolHold = value; }
}
#endregion 性能优化
#endregion 创建时的设置项
#region 常用属性
///
/// 检查通信组件是否已启动
///
public bool HasStarted => _client.HasStarted;
///
/// 状态
///
public ServiceState State => _client.State;
///
/// 是否已连接
///
public bool IsConnected => _client.IsConnected;
///
/// 是否为安全连接(SSL/HTTPS)
///
public bool IsSecure => _client.IsSecure;
///
/// 获取该组件对象的连接Id
///
public IntPtr ConnectionId => _client.ConnectionId;
#endregion 常用属性
#region 常用方法
#region 启动并连接到服务器
///
/// 启动通讯组件并连接到服务器
///
///
public bool Connect() => _client.Connect();
///
/// 启动通讯组件并连接到服务器
///
/// 远程服务器地址
/// 远程服务器端口
///
public bool Connect(string address, ushort port) => _client.Connect(address, port);
#endregion 启动并连接到服务器
///
/// 停止服务
///
///
public bool Stop() => _client.Stop();
#region 发送数据
///
/// 发送数据
///
/// 数据包
/// 数据包长度
///
public bool Send(byte[] bytes, int length) => _client.Send(bytes, length);
///
/// 发送数据
///
/// 数据包
/// 针对bytes的偏移
/// 数据包长度
///
public bool Send(byte[] bytes, int offset, int length) => _client.Send(bytes, offset, length);
///
/// 发送多组数据 向指定连接发送多组数据 TCP - 顺序发送所有数据包
///
/// 发送缓冲区数组
/// 发送缓冲区数目
/// true.成功,false.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendPackets(Wsabuf[] buffers, int count) => _client.SendPackets(buffers, count);
#endregion 发送数据
#region 发送本地小文件
///
/// 发送本地小文件
// 向指定连接发送 4096 KB 以下的小文件
///
/// 文件路径
/// 头部附加数据
/// 尾部附加数据
/// true.成功,false.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendSmallFile(string filePath, ref Wsabuf head, ref Wsabuf tail) => _client.SendSmallFile(filePath, ref head, ref tail);
///
/// 发送本地小文件
/// 向指定连接发送 4096 KB 以下的小文件
///
/// 文件路径
/// 头部附加数据,可以为null
/// 尾部附加数据,可以为null
/// true.成功,false.失败,可通过 SYSGetLastError() 获取 Windows 错误代码
public bool SendSmallFile(string filePath, byte[] head, byte[] tail) => _client.SendSmallFile(filePath, head, tail);
#endregion 发送本地小文件
#region 查询连接信息
///
/// 获取监听socket的地址信息
///
///
///
///
public bool GetListenAddress(out string host, out ushort port) => _client.GetListenAddress(out host, out port);
///
/// 获取连接的远程主机信息
///
///
///
///
public bool GetRemoteHost(out string host, out ushort port) => _client.GetRemoteHost(out host, out port);
///
/// 获取连接中未发出数据的长度
///
///
///
public bool GetPendingDataLength(out int length) => _client.GetPendingDataLength(out length);
#endregion 查询连接信息
///
/// 等待代理结果
///
/// 连接成功返回true, 连接失败返回false
//public async Task WaitProxyAsync() => await _client.WaitProxyAsync();
#endregion 常用方法
#region 创建TCPClient并连接示例
///
/// 创建TCP侦听 -示例
///
/// 地址
/// 端口
///
public ITcpClient CreateTcpServerDemo(string localAddr, int port)
{
// <2>配置TCPServer的参数
_client.Address = localAddr; // IP
_client.Port = (ushort)port; // 端口
_client.SocketBufferSize = 4096; // 缓存4K
//_client.BindAddress = ""; // 本地绑定到哪个ip
//_client.BindPort = 0; // 本地绑定到哪个端口
// <3> 绑定事件
//event ClientPrepareConnectEventHandler OnPrepareConnect; // 准备连接了事件
//event ClientConnectEventHandler OnConnect; // 连接事件
//event ClientHandShakeEventHandler OnHandShake; // TCP握手成功事件
//event ClientSendEventHandler OnSend; // 数据包发送事件
//event ClientReceiveEventHandler OnReceive; // 数据包到达事件
//event ClientCloseEventHandler OnClose; // TCP连接关闭事件
_client.OnPrepareConnect += OnPrepareConnect; // 准备连接了事件
_client.OnConnect += OnConnect; // 连接事件
_client.OnHandShake += OnHandShake; // TCP握手成功事件
_client.OnSend += OnSend; // 数据包发送事件
_client.OnReceive += OnReceive; // 数据包到达事件
_client.OnClose += OnClose; // TCP连接关闭事件
//_client.Connect(); // 连接
return _client;
}
#region 事件
///
/// 准备连接了事件
///
/// 客户端
/// 客户端Id
///
private HandleResult OnPrepareConnect(IClient sender, IntPtr socket)
{
sender.ExtraData = string.Empty; // 设置附加数据(用来做粘包处理)
return HandleResult.Ok;
}
///
/// 连接事件
///
/// 客户端
///
private HandleResult OnConnect(IClient sender)
{
//ShowLog(string.Format("TCP客户端([{0}]{1}:{2})接入TCP服务器{3}:{4}", sender.ConnectionId, sender.BindAddress, sender.BindPort, sender.Address, sender.Port));
return HandleResult.Ok;
}
///
/// TCP握手成功事件
///
/// 客户端
///
private HandleResult OnHandShake(IClient sender)
{
// 一般用不到
return HandleResult.Ok;
}
///
/// 数据包发送事件
///
/// 客户端
/// 数据
///
private HandleResult OnSend(IClient sender, byte[] data)
{
//ShowLog(string.Format("TCP客户端发送数据到TCP服务器[{0}]{1}:{2};数据内容[长度{3}]:{4}", sender.ConnectionId, sender.Address, sender.Port, data.Length, Encoding.UTF8.GetString(data)));
return HandleResult.Ok;
}
///
/// 数据包到达事件
///
/// 客户端
/// 数据
///
private HandleResult OnReceive(IClient sender, byte[] data)
{
// <1> 获取附加数据对象
if (!(sender.ExtraData is string))
{
return HandleResult.Error;
}
string extraDataStr = (string)sender.ExtraData;
// <2> 将接收数据转换成字符串
string msg = Encoding.UTF8.GetString(data);
extraDataStr += msg; // 添加数据到缓存_不合格的数据添加到缓存区(用于粘包、拆包)
// <3> 显示信息
//ShowLog(string.Format("TCP客户端接收到TCP服务器[ID:{0},IP:‘{1}:{2}’]的信息;数据:[长度{3}]: {4}", sender.ConnectionId, sender.Address, sender.Port, data.Length, msg));
// <4> 处理数据
HandleResult result;
string _endsWith = "\r\n";
while (true)
{
int index = extraDataStr.IndexOf(_endsWith);
if (index == -1) // 数据接收不完整,忽略后等待下一次接收
{
result = HandleResult.Ignore;
break;
}
else
{
string validMsg = extraDataStr.Remove(0, index);
// <6> 业务处理-异步(validMsg内容解析时的格式校验属于业务范畴)
// <7> 移除已取出数据
extraDataStr = extraDataStr.Remove(0, index + _endsWith.Length);
}
}
// <5> 保存PacketData数据
if (extraDataStr.Length > _client.SocketBufferSize) // 可选-控制长度为4096(注:实际所占空间大小>4096)
{
int length_Delete = extraDataStr.Length - Convert.ToInt32(_client.SocketBufferSize);
extraDataStr = extraDataStr.Remove(0, length_Delete); // 清除长度超标数据
}
sender.ExtraData = extraDataStr; // 初始化附加信息
return result;
}
///
/// TCP连接关闭事件
///
/// 客户端
/// 关闭类型
/// 错误代码
///
private HandleResult OnClose(IClient sender, SocketOperation socketOperation, int errorCode)
{
sender.ExtraData = null; // 删除附加数据
//ShowLog(string.Format("TCP客户端断开与TCP服务器[{0}] {1}:{2}的连接, 断开类型: {3},错误代码: {4}", sender.ConnectionId, sender.Address, sender.Port, socketOperation.ToString(), errorCode));
return HandleResult.Ok;
}
#endregion 事件
#endregion 创建TCPClient并连接示例
#endregion 发送端(客户端)
}
}