1. Resolved the hourly connection termination problem in non-TLS firmware communication.

2. Enhanced socket-level data packet reception throughput.
This commit is contained in:
CoderShen
2025-11-24 16:49:05 +08:00
committed by lircy
parent b7d6993fa3
commit ada79f2073
19 changed files with 116 additions and 18 deletions

View File

@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using S7CommPlusDriver;
using S7CommPlusDriver.ClientApi;
@@ -38,6 +39,7 @@ namespace DriverTest
stopwatch1.Start();
res = conn.Connect(HostIp, Password);
stopwatch1.Stop();
byte[] var1_crc_bytes = { 0x88, 0xdd, 0xa4, 0x83, 0x34 };
Console.WriteLine($"PLCType: {conn.PLCInformation.PLCType} | MLFB: {conn.PLCInformation.MLFB} | Firmware: {conn.PLCInformation.Firmware}");
Console.WriteLine($"连接耗时{stopwatch1.ElapsedMilliseconds}ms.");
if (res == 0)
@@ -59,17 +61,13 @@ namespace DriverTest
Console.WriteLine("Main - Lese Werte aller Variablen aus");
List<PlcTag> taglist = new List<PlcTag>();
PlcTags tags = new PlcTags();
foreach (var v in vars_)
{
ItemAddress itemAddress = new ItemAddress(v.AccessSequence);
//S7p.DecodeUInt32Vlq(new MemoryStream(var1_crc_bytes), out itemAddress.SymbolCrc);
taglist.Add(PlcTags.TagFactory(v.Name, itemAddress, v.Softdatatype));
}
foreach (var t in taglist)
{
tags.AddTag(t);
}
if (res == 0)
{
Console.WriteLine("====================== VARIABLENHAUSHALT ======================");
@@ -85,13 +83,21 @@ namespace DriverTest
}
}
#endregion
Console.WriteLine("按任意键开始读");
Console.WriteLine("按任意键开始读或订阅");
Console.ReadKey();
res = conn.SubscriptionCreate(taglist, 100);
if (res == 0)
{
Task.Run(() =>
{
conn.TestWaitForVariableChangeNotifications(50000000000);
});
}
while (res == 0)
{
System.Diagnostics.Stopwatch stopwatch2 = new System.Diagnostics.Stopwatch();
stopwatch2.Start();
res = tags.ReadTags(conn);
res = PlcTags.ReadTags(conn, taglist);
stopwatch2.Stop();
long ms = stopwatch2.ElapsedMilliseconds;
if (res == 0)
@@ -99,7 +105,7 @@ namespace DriverTest
string header = $"读取{vars_.Count}个变量耗时{ms}毫秒";
Console.WriteLine(header);
}
System.Threading.Thread.Sleep(10);
//System.Threading.Thread.Sleep(50);
}
#endif
@@ -196,4 +202,80 @@ namespace DriverTest
Console.ReadKey();
}
}
public static class S7SymbolCrc32
{
private const uint Polynomial = 0xFA567993; // 多项式(x³² + x³¹ + x³⁰ + x²⁹ + x²⁸ + x²⁶ + x²³ + x²¹ + x¹⁹ + x¹⁸ + x¹⁵ + x¹⁴ + x¹³ + x¹² + x⁹ + x⁸ + x⁴ + x + 1)
private const uint InitialValue = 0xFFFFFFFF;
private static readonly uint[] Table;
static S7SymbolCrc32()
{
// 预计算CRC表
Table = new uint[256];
for (uint i = 0; i < 256; i++)
{
uint crc = i << 24;
for (int j = 0; j < 8; j++)
{
if ((crc & 0x80000000) != 0)
{
crc = (crc << 1) ^ Polynomial;
}
else
{
crc <<= 1;
}
}
Table[i] = crc;
}
}
/// <summary>
/// 计算S7CommPlus符号名的CRC32校验和
/// </summary>
/// <param name="symbolName">符号名(如"DB1.TempBottom"</param>
/// <param name="dataType">数据类型字节</param>
/// <returns>CRC32校验和</returns>
public static uint CalculateSymbolCrc(string symbolName)
{
// 1. 替换分隔符 '.' → 0x09
string processedName = symbolName.Replace('.', '\t');
// 2. 转换为字节数组
byte[] nameBytes = Encoding.ASCII.GetBytes(processedName);
// 3. 添加数据类型字节
byte[] data = new byte[nameBytes.Length];
Array.Copy(nameBytes, 0, data, 0, nameBytes.Length);
// 4. 计算CRC32
uint crc = InitialValue;
foreach (byte b in data)
{
crc = (crc << 8) ^ Table[((crc >> 24) & 0xFF) ^ b];
}
// 5. 根据作者提示,可能需要再次计算(需要验证)
//crc = CalculateSecondPass(crc);
return crc;
}
// 如果需要二次计算的方法
public static uint CalculateSecondPass(uint firstResult)
{
byte[] crcBytes = BitConverter.GetBytes(firstResult);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(crcBytes); // 确保大端序
}
uint crc = InitialValue;
foreach (byte b in crcBytes)
{
crc = (crc << 8) ^ Table[((crc >> 24) & 0xFF) ^ b];
}
return crc;
}
}
}