!提交代码
This commit is contained in:
223
WCS.BLL/Tool/TCPClient.cs
Normal file
223
WCS.BLL/Tool/TCPClient.cs
Normal file
@ -0,0 +1,223 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text;
|
||||
using TouchSocket.Core;
|
||||
using TouchSocket.Sockets;
|
||||
|
||||
|
||||
namespace WCS.BLL
|
||||
{
|
||||
/// <summary>
|
||||
/// 对TouchSocket的封装 主要完成TCP的连接 状态更新 发送接收通信
|
||||
/// </summary>
|
||||
public class TCPClient
|
||||
{
|
||||
public string RemoteIPHost { get; set; } = "127.0.0.1:20002";
|
||||
|
||||
public string BindIPHost { get; set; } = "127.0.0.1:20003";
|
||||
|
||||
public bool IsOnline { get; set; } = false;
|
||||
|
||||
//can模块协议前缀
|
||||
public readonly byte[] Prefix = new byte[] { 0x08, 0x00, 0x00 };
|
||||
//can模块协议前缀长度
|
||||
public readonly int PreFixLength = 3;
|
||||
//协议数据部分长度
|
||||
public readonly int DataLength = 10;
|
||||
|
||||
public ConcurrentDictionary<int, MessageDto> MessageList { get; set; } = new ConcurrentDictionary<int, MessageDto>();
|
||||
|
||||
public TcpClient tcpClient { get; set; }
|
||||
|
||||
public object receivdLockObject = new object();
|
||||
public object sendLockObject = new object();
|
||||
|
||||
public bool Connect()
|
||||
{
|
||||
try
|
||||
{
|
||||
tcpClient.Connect();//调用连接,当连接不成功时,会抛出异常。
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//连接失败
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化配置连接
|
||||
/// </summary>
|
||||
/// <param name="remoteIPHost"></param>
|
||||
public TCPClient(string remoteIPHost, string bindIPHost)
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoteIPHost = remoteIPHost;
|
||||
BindIPHost = bindIPHost;
|
||||
|
||||
tcpClient = new TcpClient();
|
||||
//载入配置
|
||||
tcpClient.Setup(new TouchSocketConfig()
|
||||
.SetRemoteIPHost(RemoteIPHost)
|
||||
.SetBindIPHost(BindIPHost)
|
||||
.ConfigurePlugins(a =>
|
||||
{
|
||||
//配置断线重连
|
||||
a.UseReconnection(-1, true, 1000);
|
||||
})
|
||||
.ConfigureContainer(a =>
|
||||
{
|
||||
//添加控制台日志注入
|
||||
a.AddConsoleLogger();
|
||||
}));
|
||||
|
||||
//添加接收事件 匹配已发送的指令
|
||||
tcpClient.Received += (client, e) =>
|
||||
{
|
||||
var data = e.ByteBlock.Buffer.Take((int)e.ByteBlock.Length).ToArray();
|
||||
e.ByteBlock.Clear();
|
||||
var len = data.Length;
|
||||
for (int index = 0; index < data.Length - PreFixLength; index++)
|
||||
{
|
||||
//协议拆包 通过前缀校验是否为完整数据包
|
||||
var prefixInData = data.Skip(index).Take(PreFixLength);
|
||||
var isEqual = prefixInData.SequenceEqual(Prefix);
|
||||
if (isEqual)
|
||||
{
|
||||
var dataTemp = data.Skip(index).Take(PreFixLength + DataLength).ToArray();
|
||||
if (dataTemp.Length < PreFixLength + DataLength)//拆包后不满足一条指令的长度
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//获取返回指令的板子ID
|
||||
var boardId = (data[PreFixLength + 0] << 8) + data[PreFixLength + 1];
|
||||
//查询当前板子是否有待验证的指令
|
||||
var message = new MessageDto();
|
||||
MessageList.TryGetValue(boardId, out message);
|
||||
//功能位校验 功能位相同视为已响应指令 删除对应的指令
|
||||
if (message?.Message[PreFixLength + 2] == dataTemp[PreFixLength + 2])
|
||||
{
|
||||
MessageList.TryRemove(boardId, out message);
|
||||
}
|
||||
index += (PreFixLength + DataLength - 1);//每次循环index会+1 所以这里-1
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
tcpClient.Connected += (client, e) =>
|
||||
{
|
||||
this.IsOnline = true;
|
||||
return EasyTask.CompletedTask;
|
||||
};
|
||||
|
||||
tcpClient.Disconnected += (client, e) =>
|
||||
{
|
||||
this.IsOnline = false;
|
||||
return EasyTask.CompletedTask;
|
||||
};
|
||||
|
||||
//配置数据重发机制
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
//TO DO如果指令未回应n次 则取消重发
|
||||
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
|
||||
await Task.Delay(3000);
|
||||
if (MessageList.Count > 0)
|
||||
{
|
||||
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
|
||||
foreach (var item in MessageList)
|
||||
{
|
||||
if (item.Value.LastSendTime < DateTime.Now.AddSeconds(3))
|
||||
{
|
||||
tcpClient.Send(item.Value.Message);
|
||||
item.Value.SendTimes++;
|
||||
item.Value.LastSendTime = DateTime.Now;
|
||||
await Task.Delay(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void Send(byte[] message)
|
||||
{
|
||||
var boardId = (message[3] << 8) + message[4];
|
||||
//记录发送指令 用于通信校验 同Id只校验最后一个指令
|
||||
////MessageList.AddOrUpdate(boardId, new MessageDto()
|
||||
////{
|
||||
//// ID = boardId,
|
||||
//// Message = message,
|
||||
////}, (key, oldValue) => oldValue = new MessageDto()
|
||||
////{
|
||||
//// ID = boardId,
|
||||
//// Message = message,
|
||||
////});
|
||||
lock (sendLockObject)
|
||||
{
|
||||
tcpClient.Send(message);
|
||||
//发送自带10ms间隔
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
//生成协议明细
|
||||
public byte[] GenerateMessage(int boardId, byte[] data)
|
||||
{
|
||||
var message = new byte[Prefix.Length + 2 + data.Length];
|
||||
var boardIdData = BitConverter.GetBytes(unchecked((short)boardId));
|
||||
// 检查是否需要交换字节
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
// 如果是小端序系统,则交换字节
|
||||
byte temp = boardIdData[0];
|
||||
boardIdData[0] = boardIdData[1];
|
||||
boardIdData[1] = temp;
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(Prefix, 0, message, 0, Prefix.Length);
|
||||
Buffer.BlockCopy(boardIdData, 0, message, Prefix.Length, boardIdData.Length);
|
||||
Buffer.BlockCopy(data, 0, message, Prefix.Length + boardIdData.Length, data.Length);
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//发送指令的记录
|
||||
public class MessageDto
|
||||
{
|
||||
public int ID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后一次发送时间
|
||||
/// </summary>
|
||||
public DateTime LastSendTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 发送内容
|
||||
/// </summary>
|
||||
public byte[] Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发送次数
|
||||
/// </summary>
|
||||
public int SendTimes { get; set; } = 0;//第几次发送
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user