这个服务器解决方案是最优的吗?
Is this server solution optimal?
我创建了从传感器接收数据的设备(大约 80k 个样本/秒)并通过 TCP/IP 将它们发送到我的 PC 应用程序。问题是有时我的设备会丢失一些数据。我想这是因为当我通过 TCP/IP 发送数据时,处理器需要一些时间来完成,然后他有一段时间没有从传感器接收数据。我注意到,当我在发送数据之前收集一些数据时,发生的次数较少,因此我在 data.Length 高于 30000 时发送数据。感谢您的建议。
有我的服务器代码:
while (true)
{
if (ClientIsConnected==1)
{
value = Convert.ToString(sensor1.Read(0)); ; // Publish the return value
DateTime currentDate = DateTime.Now;
long elapsedTicks = currentDate.Ticks - startDate.Ticks;
TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
time = Convert.ToString(elapsedTicks / 100);
data.Append("[" + value + " " + time + "]" + "/n");
if (data.Length > 30000)
{
serverTcp.Send(socket, Convert.ToString(data));
data.Clear();
}
}
}
编辑两个不同的线程代码:
object msg = null;
if (ClientIsConnected==1)
{
var threadTcp = new Thread(() =>
{
server.Send(socket, Convert.ToString(data));
});
var threadReadAdc = new Thread(() =>
{
value = Convert.ToString(Sensor1.Read(0)); ; // Publish the return value
DateTime currentDate = DateTime.Now;
long elapsedTicks = currentDate.Ticks - startDate.Ticks;
TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
time = Convert.ToString(elapsedTicks / 100);
data = data.Append("[" + value + " " + time + "]" + "\n");
if (data.Length > 30000)
{
msg = Convert.ToString(data);
data.Clear();
}
});
threadReadAdc.Start();
threadTcp.Start();
}
我会在这里使用类似 BlockingCollection<string>
的东西
您可以设置一个字符串集合,在一个线程中写入集合,在另一个线程中读取。读取可以将结果存储在缓冲区中,并在缓冲区足够满时通过 TCP 发送(或者已经过足够的时间 - 这取决于您)。
阻塞集合是线程安全的,读会阻塞直到有东西可读。
例如
var data = new BlockingCollection<string>();
Task taskWrite = Task.Run(() =>
{
while(true)
{
var sensorReading = Convert.ToString(sensor1.Read(0)); // Do your string time/formatting here too - I left it off for clarity
data.Add(sensorReading);
}
});
Task taskRead = Task.Run(() => {
var buffer = List<string>();
while(true)
{
if(buffer.Count > 30000)
{
// Grab contents of buffer and send via TCP
server.Send(socket, String.Join("\n", buffer));
buffer.Clear();
}
else
{
// Consume the next sensor value from the collection
buffer.Add(data.Take());
}
}
});
如果您想确保不会用值填满内存(例如,如果您的读取速度比写入速度快得多),您还可以在阻塞集合上设置界限。
我创建了从传感器接收数据的设备(大约 80k 个样本/秒)并通过 TCP/IP 将它们发送到我的 PC 应用程序。问题是有时我的设备会丢失一些数据。我想这是因为当我通过 TCP/IP 发送数据时,处理器需要一些时间来完成,然后他有一段时间没有从传感器接收数据。我注意到,当我在发送数据之前收集一些数据时,发生的次数较少,因此我在 data.Length 高于 30000 时发送数据。感谢您的建议。 有我的服务器代码:
while (true)
{
if (ClientIsConnected==1)
{
value = Convert.ToString(sensor1.Read(0)); ; // Publish the return value
DateTime currentDate = DateTime.Now;
long elapsedTicks = currentDate.Ticks - startDate.Ticks;
TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
time = Convert.ToString(elapsedTicks / 100);
data.Append("[" + value + " " + time + "]" + "/n");
if (data.Length > 30000)
{
serverTcp.Send(socket, Convert.ToString(data));
data.Clear();
}
}
}
编辑两个不同的线程代码:
object msg = null;
if (ClientIsConnected==1)
{
var threadTcp = new Thread(() =>
{
server.Send(socket, Convert.ToString(data));
});
var threadReadAdc = new Thread(() =>
{
value = Convert.ToString(Sensor1.Read(0)); ; // Publish the return value
DateTime currentDate = DateTime.Now;
long elapsedTicks = currentDate.Ticks - startDate.Ticks;
TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
time = Convert.ToString(elapsedTicks / 100);
data = data.Append("[" + value + " " + time + "]" + "\n");
if (data.Length > 30000)
{
msg = Convert.ToString(data);
data.Clear();
}
});
threadReadAdc.Start();
threadTcp.Start();
}
我会在这里使用类似 BlockingCollection<string>
的东西
您可以设置一个字符串集合,在一个线程中写入集合,在另一个线程中读取。读取可以将结果存储在缓冲区中,并在缓冲区足够满时通过 TCP 发送(或者已经过足够的时间 - 这取决于您)。
阻塞集合是线程安全的,读会阻塞直到有东西可读。
例如
var data = new BlockingCollection<string>();
Task taskWrite = Task.Run(() =>
{
while(true)
{
var sensorReading = Convert.ToString(sensor1.Read(0)); // Do your string time/formatting here too - I left it off for clarity
data.Add(sensorReading);
}
});
Task taskRead = Task.Run(() => {
var buffer = List<string>();
while(true)
{
if(buffer.Count > 30000)
{
// Grab contents of buffer and send via TCP
server.Send(socket, String.Join("\n", buffer));
buffer.Clear();
}
else
{
// Consume the next sensor value from the collection
buffer.Add(data.Take());
}
}
});
如果您想确保不会用值填满内存(例如,如果您的读取速度比写入速度快得多),您还可以在阻塞集合上设置界限。