對於一個學校項目,我正在編寫一個UDP偵聽器(使用C#),它將接收數千個UDP數據包並將數據保存到數據庫(模擬)中。現在它將數據保存在遠程數據庫中。什麼是最好的方法來處理數千個UDP數據包並將它們保存到使用線程的遠程數據庫中?
我想知道什麼是最好的方式來聽包,失去儘可能少。
所以,我有一個線程,只偵聽數據包,當收到一個數據包時,我創建一個新線程來解析並將接收到的消息保存到遠程數據庫,後者將會有一個網頁顯示數據。
1 - 我應該創建線程來處理每個數據包還是有更好的方法?最多允許多少個線程?
2 - 我正在考慮使用本地數據庫而不是遠程數據庫來爲UDP偵聽器存儲數據。我認爲每條線索都將以這種方式更快結束。還有一個網頁將使用相同的數據庫來顯示客戶端的信息(該數據庫是php服務器的本地數據庫)。該網頁也會查詢數據庫很多,我不知道哪個是最好的...對於數據庫是UDP偵聽器的本地數據庫,或者是創建網頁的PHP服務器的本地數據庫。
3 - 應該有db.query()的鎖嗎?我有它的評論,它似乎工作正常。這個函數是對數據庫的插入。
4 - 有些人告訴我,我應該在每次插入之前/之後打開()/關閉()數據庫連接...現在,當我啓動偵聽器並僅檢查它是否關閉之前打開它插入。
5 - 在這種情況下Async/Await可以幫助我的代碼嗎?也許使用Async插入數據庫會使線程更快結束?
6 - 我在DataGridView上顯示數據,但這似乎很慢,有沒有更好的方法在主窗體上顯示數據?
我將實施一種方法,以便每個接收到的數據包得到確認,並且如果ack失敗,客戶端將重新發送,但我仍然希望在每分鐘接收幾千個數據包時儘可能少地失敗。
有關如何使此過程更好的任何意見,將不勝感激。
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) { }
}
不要啓動顯式線程來處理UDP連接,更不用說每個數據包,因爲它不會擴展,您無疑會耗盡操作系統。而是使用IOCP,如通過**異步/等待提供** – MickyD