Dobra, ponieważ UDP jest bezpołączeniowy to jakiekolwiek utrzymywanie połączenia nie ma sensu. Zrobiłem tak, że w jednym wątku odbieram pakiety:
while (true)
{
Byte[] data = server.Receive(ref remote);
}
Czy odebrane ramki od klientów warto dodawać do kolejki MessageQueue i potem w kolejnym wątku je dekodować? Czyli problem producent-konsument. A może żeby nie zgubić żadnego pakietu trzeba używać jakoś metody BeginReceive i Callbacki? Czy ktoś mi objaśni jak to się powinno robić? Bo na raz 300 klientów może próbować się komunikować z serwerem i wobec tego odbieranie pakietów i ich obsługa muszą być wydajne tak żeby pakiety nie ginęły.
Znalazłem taki przykład z obsługą kolejki:
Queuing packets for background processing - High packet rate capture (Example QueuingPacketsForBackgroundProcessing in the source package)
Packet rates can exceed the rate at which they can be processed by the callback routines. This can occur if the packet processing code is time intensive, such as writing to disk, or if the packet processing code is performing advanced logic. Sometimes it is possible to reduce packet rates by applying bnf filters but in other cases these filters can be complex.
If packet rates only exceed the rate of processing for short periods of time it is possible to simply defer packet processing until periods of less activity. One technique for this is to queue the packets and process them in a background thread as shown in this example.
/// <summary>
/// Checks for queued packets. If any exist it locks the QueueLock, saves a
/// reference of the current queue for itself, puts a new queue back into
/// place into PacketQueue and unlocks QueueLock. This is a minimal amount of
/// work done while the queue is locked.
///
/// The background thread can then process queue that it saved without holding
/// the queue lock.
/// </summary>
private static void BackgroundThread()
{
while(!BackgroundThreadStop)
{
bool shouldSleep = true;
lock(QueueLock)
{
if(PacketQueue.Count != 0)
{
shouldSleep = false;
}
}
if(shouldSleep)
{
System.Threading.Thread.Sleep(250);
}
else // should process the queue
{
List<RawCapture> ourQueue;
lock(QueueLock)
{
// swap queues, giving the capture callback a new one
ourQueue = PacketQueue;
PacketQueue = new List<RawCapture>();
}
Console.WriteLine("BackgroundThread: ourQueue.Count is {0}", ourQueue.Count);
foreach(var packet in ourQueue)
{
var time = packet.Timeval.Date;
var len = packet.Data.Length;
Console.WriteLine("BackgroundThread: {0}:{1}:{2},{3} Len={4}",
time.Hour, time.Minute, time.Second, time.Millisecond, len);
}
// Here is where we can process our packets freely without
// holding off packet capture.
//
// NOTE: If the incoming packet rate is greater than
// the packet processing rate these queues will grow
// to enormous sizes. Packets should be dropped in these
// cases
}
}
}
i w wątku:
while(true)
{
// lock QueueLock to prevent multiple threads accessing PacketQueue at
// the same time
lock(QueueLock)
{
PacketQueue.Add(e.Packet);
}
}
No i jest pytanie co zrobić jak liczba pakietów w kolejce zacznie szybko przewyższać liczbę pakietów przetwarzanych w jednostce czasu?