Laden...

Empfangen mehrerer gleicher Pakete bei der Nutzung von RAW Sockets

Erstellt von die_pest vor 7 Jahren Letzter Beitrag vor 7 Jahren 2.431 Views
D
die_pest Themenstarter:in
22 Beiträge seit 2010
vor 7 Jahren
Empfangen mehrerer gleicher Pakete bei der Nutzung von RAW Sockets

Hallo,

für ein aktuelles Projekt nutze ich RAW Sockets um eingehenden und ausgehenden Datenverkehr eines Netzweradapters zu erfassen. Das ist recht einfach und funktioniert auch gut. Allerdings kommt es immer wieder vor, dass Pakete doppelt erkannt werden. Wird also beispielsweise ein UDP Paket über den Adapter abgeschickt, werden beim RAW Socket 2 Pakete empfangen. Wenn man dann die Header ausliest hat man 2 fast identische Pakete, nur dass das eine Paket vollständig ist und beim 2. Paket die Checksumme immer 0 ist.

Hier der Code den ich verwende:


            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
            listener.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
            listener.ExclusiveAddressUse = false;

            // Bind the socket to the local network interface.
            IPEndPoint endpoint = new IPEndPoint(localIP, 0);
            listener.Bind(endpoint);

            byte[] inVal = new byte[4] { 1, 0, 0, 0 };
            byte[] outVal = new byte[4];

            listener.IOControl(IOControlCode.ReceiveAll, inVal, outVal);

            // The data buffer;
            byte[] data = new byte[4096];

            State s = new State();
            s.Socket = listener;
            s.Data = data;

            listener.BeginReceive(data, 0, data.Length, SocketFlags.None, RecieveCallback, s);
        }

        private void RecieveCallback(IAsyncResult result)
        {
            State s = result.AsyncState as State;
            Socket listener = s.Socket;
            EndPoint ep = new IPEndPoint(IPAddress.Any, 0);

            // Go on waiting for data.
            byte[] data = new byte[4096];
            State newState = new State();
            newState.Socket = listener;
            newState.Data = data;

                try
                {
                    // Recieve more data.
                    listener.BeginReceive(data, 0, data.Length, SocketFlags.None, RecieveCallback,    newState);

                    // End Reading the recieved data.
                    so.Recieved = listener.EndReceive(result);

                    readMessage(so);
                }
                catch { }
            }
        }    


Ich kann mir vorstellen, dass das irgendwas mit dem asynchronen Empfangen am Raw Socket zu tun hat. Kann mir irgend jemand sagen, woher dieser Fehler kommt?

LG die_pest

1.029 Beiträge seit 2010
vor 7 Jahren

Hi,

ohne jemals damit gearbeitet zu haben finde ich es auffällig, dass du 2 Mal BeginReceive aufrufst. Das wäre jedenfalls mein Ansatzpunkt.

LG

3.170 Beiträge seit 2006
vor 7 Jahren

Hallo,

dass du 2 Mal BeginReceive aufrufst.

kann man IMO schon so machen -> In der Callback wird direkt der nächste asynchrone Lesevorgang gestartet, das sollte funktionieren.

Aber die Aufrufreihenfolge ist seltsam, ich würde auf jeden Fall zunächst mal über EndReceive die vorhandenen Daten lesen, und erst danach wieder BeginReceive aufrufen.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

W
872 Beiträge seit 2005
vor 7 Jahren

Die Dokumentation sagt explizit, daß ein BeginReceive mit einem EndReceive beendet werden muss.

D
die_pest Themenstarter:in
22 Beiträge seit 2010
vor 7 Jahren

Hi,
ja stimmt die Reichenfolge von EndRecieve und BeginRecieve war auch mein erster Gedanke, deshalb habe ich es auch so versucht:


                try
                {
                    // End Reading the recieved data.
                    so.Recieved = listener.EndReceive(result);

                    // Recieve more data.
                    listener.BeginReceive(data, 0, data.Length, SocketFlags.None, RecieveCallback,    newState);

                    readMessage(so);
                }
                catch { }

Das hatte jedoch das gleiche Resultat zu Folge. Hat jemand noch eine andere Idee?

LG

3.170 Beiträge seit 2006
vor 7 Jahren

Hallo,

bei genauerem Hinsehen frage ich mich, wie da überhaupt irgendwas funktioniert:

Du erstellst beim ersten Aufruf ein State-Objekt und steckst einen in der Methode lokal erzeugten Puffer rein. Allerdings greifst Du nach dem Lesen gar nicht auf diesen Puffer zu...
Irgendwo innerhalb der RecieveCallback müsste doch auch mal s.Data zugegriffen werden.
Ich frage mich, wie Dein readMessage überhaupt an die Daten kommt.

Deshalb erst mal die Frage:

                    so.Recieved = listener.EndReceive(result);

                    readMessage(so);

Was ist hier so, und was macht readMessage, um an die Daten zu kommen?

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

D
die_pest Themenstarter:in
22 Beiträge seit 2010
vor 7 Jahren

Hallo,

du hast recht. Es hat sich in den Code ein Fehler geschlichen.
Statt "so" sollte da eigentlich "s" stehen und in readMessage werden die Informationen mit s.Data ausgelesen.

                try
                {
                    // End Reading the recieved data.
                    s.Recieved = listener.EndReceive(result);

                    // Recieve more data.
                    listener.BeginReceive(data, 0, data.Length, SocketFlags.None, RecieveCallback,    newState);

                    readMessage(s);
                }
                catch { }

LG