2009-05-25 3 views
0

Ich erhalte von Sockel A und schreibe das auf Socket B im laufenden Betrieb (wie ein Proxy-Server könnte). Ich möchte Daten, die durchgehen, untersuchen und möglicherweise ändern. Meine Frage ist, wie man mit Grenzfällen umgehen soll, dh wo der reguläre Ausdruck, nach dem ich suche, zwischen zwei aufeinander folgenden Lese- und Socket-B-Schreibiterationen passen würde.Überprüfen von C-Pipelines durch ein Programm - Grenzfälle

char buffer[4096] 
int socket_A, socket_B 

/* Setting up the connection goes here */ 

for(;;) { 

    recv(socket_A, buffer, 4096, 0); 

    /* Inspect, and possibly modify buffer */ 

    send(socket_B, buffer, 4096, 0); 

    /* Oops, the matches I was looking for were at the end of buffer, 
    * and will be at the beginning of buffer next iteration :(*/ 

} 

Antwort

1

Mein Vorschlag: zwei Puffer und drehen zwischen ihnen:

  1. Recv Puffer 1
  2. Recv Puffer 2
  3. Prozess.
  4. Sendepuffer 1
  5. Recv Puffer 1
  6. Prozess, aber mit Puffer 2 vor Puffer 1.
  7. Sendepuffer 2
  8. Goto 2.

Oder so ähnlich?

1

Angenommen, Sie kennen die maximale Länge M des möglichen regulären Ausdrucks (oder können mit einem beliebigen Wert leben - oder verwenden Sie einfach den gesamten Puffer), könnten Sie damit umgehen, indem Sie nicht den vollen Puffer übergeben, sondern M-1 behalten Bytes zurück. In der nächsten Iteration setzen Sie die neuen empfangenen Daten am Ende der M-1 Bytes und wenden Sie den regulären Ausdruck an.

Wenn Sie das Format der übertragenen Daten kennen (z. B. http), sollten Sie den Inhalt analysieren können, um zu wissen, wann Sie das Ende der Kommunikation erreicht haben und die möglicherweise zwischengespeicherten Bytes senden sollten. Wenn Sie das Format nicht kennen, müssen Sie im recv ein Timeout implementieren, damit Sie nicht zu lange am Ende der Kommunikation bleiben. Was zu lang ist, müssen Sie selbst entscheiden,

0

Grundsätzlich besteht das Problem mit Ihrem Code darin, dass die recv/send-Schleife auf einer niedrigeren Netzwerkschicht als Ihre Änderungen arbeitet. Wie Sie dieses Problem lösen, hängt davon ab, welche Änderungen Sie vornehmen. Es beinhaltet jedoch wahrscheinlich das Puffern der Daten, bis alle lokalen Änderungen vorgenommen werden können.

EDIT: Ich kenne keine Regex-Bibliothek, die einen solchen Stream filtern kann. Wie schwer das sein wird, hängt von Ihrer Regex und dem zu filternden Protokoll ab.

1

In diesem Sinne sprechen Sie über (und alle Sinne für, sagen wir TCP) Sockets sind Streams. Aus Ihrer Frage ergibt sich, dass Sie eine Struktur in den Daten haben. Sie müssen also etwas Ähnliches wie das Folgende tun:

  1. Puffer (halten) eingehende Daten, bis eine Grenze erreicht ist. Die Grenze kann ein End-of-Line-, End-of-Record- oder ein anderer Weg sein, von dem Sie wissen, dass Ihre Regex übereinstimmen wird.
  2. Wenn ein "Datensatz" bereit ist, verarbeiten Sie es und platzieren Sie die Ergebnisse in einem Ausgabepuffer.
  3. Schreiben Sie alles, was sich im Ausgabepuffer angesammelt hat.

Das behandelt die meisten Fälle. Wenn Sie einen der seltenen Fälle haben, in denen es wirklich keine "Aufzeichnung" gibt, dann müssen Sie eine Art von Zustandsmaschine (DFA) erstellen. Damit meine ich, dass Sie in der Lage sein müssen, Daten zu akkumulieren, bis entweder a) es nicht mit Ihrer Regex übereinstimmen kann, oder b) es ein abgeschlossenes Spiel ist.

EDIT: Wenn Sie feste Zeichenketten passend anstelle eines echten regex dann sollten Sie in der Lage sein, den Boyer-Moore Algorithmus zu verwenden, die in sublinear Zeit tatsächlich ausgeführt werden kann (durch Überspringen Zeichen). Wenn Sie es richtig machen, können Sie, während Sie über die Eingabe gehen, zuvor gesehene Daten in den Ausgabepuffer werfen, was die Latenz verringert und den Durchsatz erheblich erhöht.

1

Sie müssen etwas über Ihren regulären Ausdruck wissen und/oder sagen.

Je nach dem regulären Ausdruck müssen Sie möglicherweise viel mehr Puffer puffern, als Sie jetzt puffern.

Ein Worst-Case-Szenario könnte etwas wie ein regulärer Ausdruck sein, der sagt: "Find alles, beginnend am Anfang bis zum ersten Vorkommen des Wortes 'Hund', und ersetzen Sie das durch etwas anderes": Wenn Sie eine haben Regulärer Ausdruck wie dieser, dann musst du alles puffern (ohne Weiterleitung) von Anfang an bis zum ersten Vorkommen des Wortes "Hund": was niemals passieren könnte, dh es könnte unendlich viel Puffer sein.

0

Eine Alternative ist die Verwendung der poll(2) -ähnlichen Strategie mit nicht blockierenden Sockeln. Bei Leseereignis einen Puffer vom Socket holen, ihn in die ankommende Warteschlange schieben, den Lexer/Parser/Matcher aufrufen, der die Puffer zu einem Strom zusammenfügt, und dann Stücke in die Ausgabewarteschlange schieben. Bei Schreib-Ereignis, nehmen Sie einen Chunk aus der Ausgabe-Warteschlange, falls vorhanden, und schreiben Sie es in den Socket. Das hört sich kompliziert an, aber man gewöhnt sich nicht an das invertierte Steuerungsmodell.

Verwandte Themen