UDP listener with linq query

Jul 26, 2013 at 1:46 PM
Hi,

I've based my program on your tutorial example for LINQ and performance was very good in console application (read, analyse, safe and display every "x" frames.
However I've decided to use GUI and in order to be able to change GUI settings i need to run PCAP listener part as background worker (or any other type of thread).

I use UDP protocol

At the moment I use this in my background function
{

            byte[] frame = new byte[65536];
PacketCommunicator communicator = Globals.selectedDevice.Open(65536,                                  // portion of the packet to capture
                // 65536 guarantees that the whole packet will be captured on all the link layers
                                    PacketDeviceOpenAttributes.NoCaptureLocal,// drop traffic sent
                                    1000);                                  // read timeout
            var query = from packet in communicator.ReceivePackets(-1) // here I've had number of packets prior to analyse, stream rate (acquisition for 1 sec prior to analyse). Now I have -1, which is = 1 ?? and continuous loop
                        where ((packet.Ethernet.IpV4.Udp.Length != 0) && (packet.Ethernet.IpV4.Source.ToString() == Globals.sourceIP))
                        //filter packets by not empty and from specified source
                        select new { packet.Timestamp, packet.Ethernet.IpV4.Udp.Payload }; //get payload and timestamp from Network Card 

            foreach (var Payload in query)
            {
                Globals.totalFrames += 1;
                frame = Payload.Payload.ToArray();
                streamID = ((frame[Globals.inetStart + 4] << 24) + (frame[Globals.inetStart + 5] << 16) + (frame[Globals.inetStart + 6] << 8) + frame[Globals.inetStart + 7]);
                

                if (streamID != Globals.streamID) //ignore streams not selected, for future use with multiple streams at once
                {
                    continue;
                }
                Save.SaveFrame(Payload.Payload, Payload.Timestamp, streamID); // Save all frames
                
                if (Globals.framesReceived[streamID][0] == 0) //set-up out files in first frame
                {                    
                    Globals.framesReceived[streamID][2] = ((frame[Globals.inetStart + 8] << 24) + (frame[Globals.inetStart + 9] << 16)
                        + (frame[Globals.inetStart + 10] << 8) + frame[Globals.inetStart + 11]) - 1;
                    logThis = delegate
                    { this.textBox1.Text = String.Format("= Listening to stream: {0} on {1} ", Globals.streamID, Globals.selectedDevice.Addresses[0].Address); };
                    this.textBox1.BeginInvoke(logThis);
                    UpdateParametersThread(frame);
                }
                else
                {
                    if (Globals.framesReceived[streamID][0] % 5 == 0) //updated labels every X frames received, 5 at the moment
                    {
                        logThis = delegate
                        { this.textBox1.Text = String.Format("= Listening to stream: {0} on {1} ", Globals.streamID, Globals.selectedDevice.Addresses[0].Address); };
                        this.textBox1.BeginInvoke(logThis);
                        UpdateParametersThread(frame);                        
                    }
                    else
                    {
                       AnalyseData(frame); // analyse only without displaying.
                    }                    
                }                
                Globals.framesReceived[streamID][0]++;
                logThis= delegate{
                this.textBox1.Text = String.Format("\n\n Dropped = {0}\t|\t Received = {1}", communicator.TotalStatistics.PacketsDroppedByInterface, communicator.TotalStatistics.PacketsCaptured);
                }; //show PCAP device stats, is this reliable?
                this.textBox1.BeginInvoke(logThis);                
            }
I would like to read streams up to 1k (or more) frames/second.
Each stream will have multiple parameters (100 or more, which equals to GUI labels to update) which I have to analyse in real-time. Most important for me at the moment is to acquire all of the packets, analyse and save them. I track frames by unique Sequence number stored in UDP payload.

Any ideas how could I receive packets in background thread and NOT loose any of the packets?
My current setup works fine with 100 parameters 10 times/second, but I think I will drop frames if I get more parameters or more packets/second.
Coordinator
Jul 27, 2013 at 8:02 AM
Hi Jackrz,

Sounds like you need to read the packet and immediately put it in some sort of queue to be handled by a different thread and move on to the next packet.
Basically - a Producer/Consumer design where the producer runs in a separate thread and does the minimum work just to receive the packet.

I hope this helps,

Boaz.