搜索netty ChannelBuffer获取字符串的最佳方法(不创建新字符串)?

时间:2013-04-30 18:13:55

标签: java netty

我使用Netty实现了代理服务器,我在其中解码HTTP请求,然后根据路径将这些请求写入传出通道。我需要从HTTP请求的内容中提取一些信息以供将来处理(基本上,找到“request-id:”形式的子字符串并记录以供以后使用。最好的方法是什么?显然,我可以将通道缓冲区的内容转储到字符串中并使用标准的java字符串搜索技术,但是在netty中执行此操作是否有直接且低开销的方法,而不创建新的字符串?例如,如果有类似的东西ChannelBuffer的asCharSequence(CharSet)方法,我可以使用java Pattern / Matcher。

3 个答案:

答案 0 :(得分:2)

我刚刚碰到这个问题,因为我试图嗅探ChannelBuffer中包含的字节的内容类型。

我突然想到你可以使用:

channelBuffer.toByteBuffer().asCharBuffer()

然后你可以传递给正则表达式Pattern.Matcher,因为这不会重新分配缓冲区,而是只是被包装并重新表示,就像它一样。但这不起作用,因为CharBuffer需要是Charset.decoded,这可能与将ChannelBuffer转换为字符串一样糟糕。

ChannelBufferIndexFinder的一个问题是,在搜索一个特定字节时,它往往效果最佳,在搜索字符串时(或者更基本上是长度> 1的字节数组) ,我无法按照我想要的方式工作。

我开始研究名为ByteSequenceIndexFinder的ChannelBufferIndexFinder实现,它有助于在ChannelBuffer中找到实际的字节序列,但是它有几个问题:

  1. 由于ChannelBuffer.bytesBefore(...)的工作方式,它不返回定位数组的直接偏移量,而是返回它的结尾,因此您必须减去字节数组长度+1 从返回的索引中获取字节缓冲区内字节序列开头的偏移量。
  2. 由于finder必须保持状态(到目前为止匹配的字节数),因此它不是线程安全的。我尝试用ThreadLocal替换简单状态(一个int),但性能大幅降低,但它仍然是一个选项。
  3. 实际上有一种非标准的替代调用方法可以解决问题#1,它的工作原理如下:

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

    startingOffset是通道缓冲区中匹配字节序列的第一个字节的偏移量。

    希望如果您需要这样的东西,它可能对您有所帮助。 This是测试用例的开始。

答案 1 :(得分:0)

你不能使用ChannelBuffer.indexOf(...)并将ChannelBufferIndexFinder传递给方法吗?

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

答案 2 :(得分:0)

我正在使用以下ChannelBufferIndexFinder的实施方式在ChannelBuffer中搜索字符串:

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()));
    }

}