For a school project, I'm writing a UDP listener (with C#) that will receive thousands of UDP packets and save the data on a database (Simulated). Right now it's saving the data on a remote database.
I'm wondering whats the best way to listen to packets and lose as few as possible.
So, I have a thread that only listens for packets, when a packet is received I create a new thread to parse and save the received message on a remote database, latter there will be a webpage that will display the data.
1 - Should I be creating threads to handle each packet or is there a better way? How many threads should be the maximum allowed?
2 - I'm thinking of using a local database instead of a remote database for the UDP listener to store the data. I think each thread will end faster this way. There is also a webpage that will use the same database to show information for the clients (The database is local to the php server) . The webpage will also query the database a lot, I'm not sure which is best... for the database to be local for the UDP listener or local for the php server creating the webpage.
3 - Should there be a lock for the db.query()? I have it commented and it seems to work fine. This function is an insert to the DB.
4 - Some people have told me I should open()/close() the database connection before/after each insert... Right now I open it when I start the listener and only check to see if it's closed before inserting.
5 - Could Async/Await help my code in this case? Maybe using Async to insert on the database will make the thread end faster?
6 - I display the data on a DataGridView, but this seems to be very slow, is there a better way to display the data on the Main Form?
I will implement a method so that each packet received is acknowledged, and the client will resend if the ack fails, but I still would like it to fail as least as possible when receiving several thousands packets each minute.
Any comments on how to make this process better will be appreciated.
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) { }
}