2 Stimmen

Beste Möglichkeit, in einem Netty ChannelBuffer nach einem String zu suchen (ohne einen neuen String zu erstellen)?

Ich habe einen Proxy-Server implementiert mit Netty, in dem ich HTTP-Anfragen decodiere und diese Anfragen dann basierend auf ihrem Pfad in einen ausgehenden Kanal schreibe. Ich muss einige Informationen aus dem Inhalt der HTTP-Anfrage extrahieren, um sie für zukünftige Verarbeitung zu verwenden (im Grunde genommen, eine Teilzeichenfolge der Form "request-id:" finden und für spätere Verwendung aufzeichnen. Was ist der beste Weg, dies zu tun? Offensichtlich könnte ich den Inhalt des Kanalpuffers in einen String schreiben und Standard-Java-String-Suchtechniken verwenden, aber gibt es einen einfachen und ressourcenschonenden Weg, dies in Netty zu tun, ohne einen neuen String zu erstellen? Zum Beispiel, wenn es so etwas wie eine asCharSequence(CharSet) Methode für ChannelBuffer geben würde, könnte ich einfach ein Java Pattern/Matcher verwenden.

2voto

Nicholas Punkte 15611

Ich bin vor einer Weile auf dieses Problem gestoßen, als ich versuchte, den Inhaltstyp der Bytes innerhalb eines ChannelBuffer zu analysieren.

Es fiel mir ein, dass du folgendes verwenden könntest:

channelBuffer.toByteBuffer().asCharBuffer()

was du dann an einen Regex Pattern.Matcher übergeben könntest, da dabei der Puffer nicht neu alloziert wird, sondern nur umhüllt und neu repräsentiert wird, sozusagen. Aber das funktioniert nicht, weil der CharBuffer in Charset.decoded sein muss, was wahrscheinlich genauso schlecht ist wie das Umwandeln des ChannelBuffer in eine Zeichenkette.

Eines der Probleme bei ChannelBufferIndexFinder ist, dass es am besten funktioniert, wenn man nach einem bestimmten Byte sucht, während es beim Suchen nach einem String (oder einfach einem Byte-Array mit einer Länge > 1) nicht so funktioniert, wie ich es wollte.

Ich habe mit der Implementierung dieses ChannelBufferIndexFinder namens ByteSequenceIndexFinder begonnen, das dabei hilft, eine tatsächliche Byte-Folge innerhalb eines ChannelBuffer zu finden, aber es gibt ein paar Probleme damit:

  1. Da ChannelBuffer.bytesBefore(...) funktioniert, gibt es nicht den direkten Offset des gefundenen Arrays zurück, sondern nur das Ende davon, daher musst du die Länge des Byte-Arrays +1 vom zurückgegebenen Index subtrahieren, um den Offset des Beginns der Byte-Folge im Byte-Puffer zu erhalten.
  2. Da der Finder den Zustand (die Anzahl der bisher übereinstimmenden Bytes) speichern muss, ist er nicht threadsicher. Ich habe versucht, den einfachen Zustand (eines Integers) durch ein ThreadLocal zu ersetzen, aber die Leistung wurde drastisch reduziert, aber es bleibt eine Option.

Es gibt eigentlich eine alternative Aufrufmethode, die nicht standardmäßig ist und Problem #1 angeht und funktioniert wie folgt:

ChannelBuffer bufferToSearch = ...;
String searchStr = "....";
ByteSequenceIndexFinder finder = new ByteSequenceIndexFinder(searchStr.getBytes());
int startingOffset = finder.findIn(bufferToSearch);

Dieser StartingOffset ist der Offset des ersten Bytes der übereinstimmenden Byte-Folge innerhalb des Kanalpuffers.

Hoffentlich kann es dir hilfreich sein, wenn du so etwas benötigst. Hier ist der Anfang eines Testfalls dafür.

0voto

Norman Maurer Punkte 22487

Kannst du ChannelBuffer.indexOf(...) verwenden und einen ChannelBufferIndexFinder an die Methode übergeben?

http://netty.io/3.6/api/org/jboss/netty/buffer/ChannelBuffer.html#indexOf(int,%20int,%20org.jboss.netty.buffer.ChannelBufferIndexFinder)

0voto

Anton Tananaev Punkte 2328

Ich verwende die folgende Implementierung von ChannelBufferIndexFinder, um nach einem String in ChannelBuffer zu suchen:

public class StringFinder implements ChannelBufferIndexFinder {

    private String string;

    public StringFinder(String string) {
        this.string = string;
    }

    @Override
    public boolean find(ChannelBuffer buffer, int guessedIndex) {

        if (buffer.writerIndex() - guessedIndex < string.length()) {
            return false;
        }

        return string.equals(buffer.toString(guessedIndex,
                string.length(), Charset.defaultCharset()));
    }

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X