Closed. This question needs to be more focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
2年前关闭。
对于一个学校项目,我正在编写一个UDP侦听器(使用C#),它将接收数千个UDP数据包并将数据保存在数据库中(模拟)。现在,它将数据保存在远程数据库中。
我想知道什么是侦听数据包并尽可能少丢失的最佳方法。
因此,我有一个仅侦听数据包的线程,当接收到数据包时,我创建了一个新线程来解析并将接收到的消息保存在远程数据库中,后者将提供一个显示数据的网页。
1-我应该创建线程来处理每个数据包还是有更好的方法?应该允许的最大线程数是多少?
2-我正在考虑使用本地数据库而不是远程数据库供UDP侦听器存储数据。我认为每个线程将以这种方式更快结束。还有一个网页将使用相同的数据库显示客户端信息(该数据库位于php服务器本地)。该网页还会查询很多数据库,我不确定哪个是最好的...数据库对于UDP侦听器来说是本地的,对于创建该网页的php服务器而言是本地的。
3-db.query()是否应该有锁?我对此发表了评论,它似乎运作良好。该功能是对数据库的插入。
4-有人告诉我我应该在每次插入之前/之后open()/ close()数据库连接...现在我在启动侦听器时将其打开,并且仅在插入之前检查它是否关闭。
5-在这种情况下,异步/等待可以帮助我的代码吗?也许使用Async插入数据库将使线程结束更快?
6-我在DataGridView上显示数据,但这似乎很慢,是否有更好的方法在Main Form上显示数据?
我将实现一种方法,以确认接收到的每个数据包,并且如果确认失败,客户端将重新发送,但是当每分钟接收数千个数据包时,我仍然希望它尽可能地失败。
任何有关如何使此过程更好的意见将不胜感激。
如果您确实想利用多个线程和连接,则可以启动
我的开始不超过处理器的核心数量。请注意,数据库仍然会成为瓶颈,因为所有连接通常都将尝试写入数据库中的同一数据页,并且会短暂地将彼此锁定,但是您仍然可以获得一些好处。
2-我正在考虑使用本地数据库而不是远程数据库供UDP侦听器存储数据。我认为每个线程将以这种方式更快结束。还有一个网页将使用相同的数据库显示客户端信息(该数据库位于php服务器本地)。该网页还会查询很多数据库,我不确定哪个是最好的...数据库对于UDP侦听器来说是本地的,对于创建该网页的php服务器而言是本地的。
本地数据库不一定更好,因为该数据库随后将与您的程序共享资源,我认为这很忙。我个人将设计该软件以在任何位置使用数据库,然后以各种配置对其进行测试。
3-db.query()是否应该有锁?我对此发表了评论,它似乎运作良好。该功能是对数据库的插入。
除非您的数据库很奇怪,否则默认锁定语义应该很好。通常,数据库是为多个客户端设计的。
4-有人告诉我我应该在每次插入之前/之后open()/ close()数据库连接...现在我在启动侦听器时将其打开,并且仅在插入之前检查它是否关闭。
通常您会为每个操作打开和关闭。开销将是最小的,因为“关闭”连接实际上并没有关闭它-它只是将其发送回连接池。 “开放”只是抢回来。
话虽如此,在您的特定情况下,保持打开状态可能是一个更好的主意,因为您只是一遍又一遍地做一件事,并且您需要使其尽快运行。另外,您不需要连接池-始终需要一个连接(每个线程)。
5-在这种情况下,异步/等待可以帮助我的代码吗?也许使用Async插入数据库将使线程结束更快?
如果您使用我建议的双线程方法,则等待和异步将无济于事。如果您有专用的工作线程,则在继续操作之前需要先
6-我在DataGridView上显示数据,但这似乎很慢,是否有更好的方法在Main Form上显示数据?
如果您的数据量很大,那么任何表单控件都将变得乏味。如果您使用绑定控件并每次刷新整个数据集,那就更糟了。尝试一次使用未绑定的DataGridView和add the data manually,一次一行。
想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
2年前关闭。
对于一个学校项目,我正在编写一个UDP侦听器(使用C#),它将接收数千个UDP数据包并将数据保存在数据库中(模拟)。现在,它将数据保存在远程数据库中。
我想知道什么是侦听数据包并尽可能少丢失的最佳方法。
因此,我有一个仅侦听数据包的线程,当接收到数据包时,我创建了一个新线程来解析并将接收到的消息保存在远程数据库中,后者将提供一个显示数据的网页。
1-我应该创建线程来处理每个数据包还是有更好的方法?应该允许的最大线程数是多少?
2-我正在考虑使用本地数据库而不是远程数据库供UDP侦听器存储数据。我认为每个线程将以这种方式更快结束。还有一个网页将使用相同的数据库显示客户端信息(该数据库位于php服务器本地)。该网页还会查询很多数据库,我不确定哪个是最好的...数据库对于UDP侦听器来说是本地的,对于创建该网页的php服务器而言是本地的。
3-db.query()是否应该有锁?我对此发表了评论,它似乎运作良好。该功能是对数据库的插入。
4-有人告诉我我应该在每次插入之前/之后open()/ close()数据库连接...现在我在启动侦听器时将其打开,并且仅在插入之前检查它是否关闭。
5-在这种情况下,异步/等待可以帮助我的代码吗?也许使用Async插入数据库将使线程结束更快?
6-我在DataGridView上显示数据,但这似乎很慢,是否有更好的方法在Main Form上显示数据?
我将实现一种方法,以确认接收到的每个数据包,并且如果确认失败,客户端将重新发送,但是当每分钟接收数千个数据包时,我仍然希望它尽可能地失败。
任何有关如何使此过程更好的意见将不胜感激。
class UdpListener
{
UdpClient listener;
int port;
byte[] receivedBytes;
byte[] sendData;
IPEndPoint ipep;
IPEndPoint sender;
Thread packetWorkerThread;
DataBase db;
MainForm mainForm;
int threadCount, queryCount;
public UdpListener(MainForm mainForm)
{
try
{
port = 1988;
ipep = new IPEndPoint(IPAddress.Any, port);
listener = new UdpClient(ipep);
sender = new IPEndPoint(IPAddress.Any, 0);
db = new DataBase();
this.mainForm = mainForm;
threadCount = queryCount = 0;
}
catch (Exception e) { }
}
public void start()
{
// Open db connection.
//-- Maybe I should open/close before/after each insert?!
if (db.connect())
{
while (true)
{
try
{
receivedBytes = listener.Receive(ref sender);
Packet packetData = new Packet(sender, ipep, receivedBytes);
if(threadCount<10)
{
//Launch Thread to process received data and save it to Database
packetWorkerThread = new Thread(p =>
{
workerThread_ProcessPacket(packetData);
});
packetWorkerThread.Start();
}
}
catch (Exception e) { }
}
}
}
private void workerThread_ProcessPacket(Packet packetData)
{
try
{
lock (this)
{
threadCount++;
queryCount++;
}
//lock (db)
//{
db.sqlQuery("SOME INSERT SQL");
//}
string data = GetHexStringFrom(packetData.ReceivedBytes);
string[] row = new string[] { DateTime.Now.ToString(), packetData.FIP, packetData.FPort, packetData.TIP, packetData.TPort, data, threadCount.ToString(), queryCount.ToString() };
mainForm.dataGridViewPackets.Invoke((MethodInvoker)delegate { mainForm.dataGridViewPackets.Rows.Add(row); });
if (mainForm.dataGridViewPackets.RowCount >= 100)
{
mainForm.dataGridViewPackets.Invoke((MethodInvoker)delegate { mainForm.dataGridViewPackets.Rows.RemoveAt(0); });
}
lock (this)
{
threadCount--;
}
}
catch (Exception e) { }
}
最佳答案
1-我应该创建线程来处理每个数据包还是有更好的方法?应该允许的最大线程数是多少?
如果是我,我将只使用两个线程;一个监听UDP,一个监听数据库。他们将通过ConcurrentQueue进行通信。
private ConcurrentQueue<Packet> _queue = new ConcurrentQueue<Packet>();
private volatile bool _cancel;
void Listener() {
while (!_cancel) {
var packet = GetNextPacket(out packet);
_queue.Enqueue(packet);
}
void Processor() {
while (!_cancel) {
Packet packet;
var ok = _queue.TryDequeue(out packet);
if (ok) {
SaveToDatabase(packet);
}
else {
Sleep(100);
}
}
}
如果您确实想利用多个线程和连接,则可以启动
Processor
的多个实例。 ConcurrentQueue
逻辑保证队列中的每个数据包仅被处理一次。我的开始不超过处理器的核心数量。请注意,数据库仍然会成为瓶颈,因为所有连接通常都将尝试写入数据库中的同一数据页,并且会短暂地将彼此锁定,但是您仍然可以获得一些好处。
2-我正在考虑使用本地数据库而不是远程数据库供UDP侦听器存储数据。我认为每个线程将以这种方式更快结束。还有一个网页将使用相同的数据库显示客户端信息(该数据库位于php服务器本地)。该网页还会查询很多数据库,我不确定哪个是最好的...数据库对于UDP侦听器来说是本地的,对于创建该网页的php服务器而言是本地的。
本地数据库不一定更好,因为该数据库随后将与您的程序共享资源,我认为这很忙。我个人将设计该软件以在任何位置使用数据库,然后以各种配置对其进行测试。
3-db.query()是否应该有锁?我对此发表了评论,它似乎运作良好。该功能是对数据库的插入。
除非您的数据库很奇怪,否则默认锁定语义应该很好。通常,数据库是为多个客户端设计的。
4-有人告诉我我应该在每次插入之前/之后open()/ close()数据库连接...现在我在启动侦听器时将其打开,并且仅在插入之前检查它是否关闭。
通常您会为每个操作打开和关闭。开销将是最小的,因为“关闭”连接实际上并没有关闭它-它只是将其发送回连接池。 “开放”只是抢回来。
话虽如此,在您的特定情况下,保持打开状态可能是一个更好的主意,因为您只是一遍又一遍地做一件事,并且您需要使其尽快运行。另外,您不需要连接池-始终需要一个连接(每个线程)。
5-在这种情况下,异步/等待可以帮助我的代码吗?也许使用Async插入数据库将使线程结束更快?
如果您使用我建议的双线程方法,则等待和异步将无济于事。如果您有专用的工作线程,则在继续操作之前需要先
await
任何先前的async
,因此您仍然无法一次处理一个数据包。6-我在DataGridView上显示数据,但这似乎很慢,是否有更好的方法在Main Form上显示数据?
如果您的数据量很大,那么任何表单控件都将变得乏味。如果您使用绑定控件并每次刷新整个数据集,那就更糟了。尝试一次使用未绑定的DataGridView和add the data manually,一次一行。
09-18 14:05