TCPDump-Buffer 上的 ReadLine 有时会阻塞,直到杀死 tcpdump

发布于 2024-11-02 09:10:42 字数 1921 浏览 4 评论 0原文

我在 Android 应用程序中使用 TCPDump 时遇到问题。 它应该逐行读取 tcpdump 的输出并在我的应用程序中处理它。
问题是:
有时代码工作正常,它会立即读取捕获的数据包。但有时,ReadLine 会阻塞,直到我从 Linux 控制台终止 tcpdump 进程(killall tcpdump)。完成此操作后,我的循环会针对每一行进行处理(有时是 10 行,有时是 1 或 2 行)——这意味着 readLine 应该有效,但没有。
我读到了类似的问题,但没有找到该问题的任何解决方案...
谢谢!!

public class ListenActivity extends Activity {

static ArrayList<Packet> packetBuffer = new ArrayList<Packet>();
static Process tcpDumpProcess = null;
static ListenThread thread = null;
public static final String TCPDUMP_COMMAND = "tcpdump -A -s0 | grep -i -e 'Cookie'\n";

private InputStream  inputStream = null;
private OutputStream outputStream = null;

@Override
protected void onStart() {
    super.onStart();
    try {
        tcpDumpProcess = new ProcessBuilder().command("su").redirectErrorStream(true).start();
        inputStream = tcpDumpProcess.getInputStream();
        outputStream = tcpDumpProcess.getOutputStream();
        outputStream.write(TCPDUMP_COMMAND.getBytes("ASCII"));
    } catch (Exception e) {
        Log.e("FSE", "", e);
    }
    thread = new ListenThread(new BufferedReader(new InputStreamReader(inputStream)));
    thread.start();
}

private class ListenThread extends Thread {

    public ListenThread(BufferedReader reader) {
        this.reader = reader;
    }

    private BufferedReader reader = null;

    @Override
    public void run() {

        reader = new BufferedReader(new InputStreamReader(inputStream));
        while (true) {
            try {                   
                String received = reader.readLine();
                Log.d("FS", received);
                Packet pReceived = Packet.analyze(received);
                if (pReceived != null) {
                    packetBuffer.add(pReceived);
                }
            } catch (Exception e) {
                Log.e("FSE", "", e);
            }

        }

    }

}

}

I have a problem using TCPDump from my Android-Application.
It is supposed to read the output from tcpdump line by line and process it within my Application.
The Problem is:
Sometimes the code works fine, it reads the captured packets immediately. But sometimes, ReadLine blocks until I kill the tcpdump process from the Linux-Console (killall tcpdump). After doing that, my loop is processed for each line (sometimes 10, sometimes 1 or 2) - which means, the readLine should have worked, but didn´t.

I read about similar problems, but did not find any solution for this problem...
THANKS!!

public class ListenActivity extends Activity {

static ArrayList<Packet> packetBuffer = new ArrayList<Packet>();
static Process tcpDumpProcess = null;
static ListenThread thread = null;
public static final String TCPDUMP_COMMAND = "tcpdump -A -s0 | grep -i -e 'Cookie'\n";

private InputStream  inputStream = null;
private OutputStream outputStream = null;

@Override
protected void onStart() {
    super.onStart();
    try {
        tcpDumpProcess = new ProcessBuilder().command("su").redirectErrorStream(true).start();
        inputStream = tcpDumpProcess.getInputStream();
        outputStream = tcpDumpProcess.getOutputStream();
        outputStream.write(TCPDUMP_COMMAND.getBytes("ASCII"));
    } catch (Exception e) {
        Log.e("FSE", "", e);
    }
    thread = new ListenThread(new BufferedReader(new InputStreamReader(inputStream)));
    thread.start();
}

private class ListenThread extends Thread {

    public ListenThread(BufferedReader reader) {
        this.reader = reader;
    }

    private BufferedReader reader = null;

    @Override
    public void run() {

        reader = new BufferedReader(new InputStreamReader(inputStream));
        while (true) {
            try {                   
                String received = reader.readLine();
                Log.d("FS", received);
                Packet pReceived = Packet.analyze(received);
                if (pReceived != null) {
                    packetBuffer.add(pReceived);
                }
            } catch (Exception e) {
                Log.e("FSE", "", e);
            }

        }

    }

}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

慢慢从新开始 2024-11-09 09:10:42

由于发送到管道的输出通常是块缓冲的,因此 tcpdump 进程 grep 进程都将等待,直到他们已收到足够的数据,无需将其发送到的程序中。 ,您很幸运,您选择使用的两个程序都准备修改其缓冲区行为(在内部使用 setvbuf(3) 函数,以防您对细节感到好奇):

不过 tcpdump(8)

   -l     Make stdout line buffered.  Useful if you want to see
          the data while capturing it.  E.g.,
          ``tcpdump  -l  |  tee dat'' or ``tcpdump  -l   >
          dat  &  tail  -f  dat''.

对于 grep(1)

   --line-buffered
          Use line buffering on output.  This can cause a
          performance penalty.

试试这个:

"tcpdump -l -A -s0 | grep --line-buffered -i -e 'Cookie'\n";

Because output sent to pipes is usually block buffered, both the tcpdump process and the grep process will be waiting until they've received enough data to bother sending it onto your program. You're very lucky though, both programs you have chosen to use are prepared to modify their buffer behavior (using the setvbuf(3) function internally, in case you're curious about the details):

For tcpdump(8):

   -l     Make stdout line buffered.  Useful if you want to see
          the data while capturing it.  E.g.,
          ``tcpdump  -l  |  tee dat'' or ``tcpdump  -l   >
          dat  &  tail  -f  dat''.

For grep(1):

   --line-buffered
          Use line buffering on output.  This can cause a
          performance penalty.

Try this:

"tcpdump -l -A -s0 | grep --line-buffered -i -e 'Cookie'\n";
北笙凉宸 2024-11-09 09:10:42

我不明白为什么,但即使使用 -l 选项,如果您读取运行 tcpdump 的进程的标准输出,缓冲区也会太大。
我通过将 TcpDump 的输出重定向到一个文件并在另一个线程中读取该文件来解决这个问题。 TcpDump 命令应该类似于:

tcpdump -l-A -s0 > /data/local/output.txt

线程内的 run 方法必须更改为在输出文件中读取:

File dumpedFile = new File("/data/local/output.txt");
//open a reader on the tcpdump output file
BufferedReader reader = new BufferedReader(new FileReader(dumpedFile));
String temp = new String();
//The while loop is broken if the thread is interrupted   
while (!Thread.interrupted()) {    
    temp = reader.readLine();
    if (temp!=null) {
        Log.e("READER",new String(temp));    
    }
}

我不完全知道你想用 grep 做什么,但我认为可以使用内部的 regexp 实现相同的操作Java 代码。

您还应该注意,TcpDump 的进程永远不会结束,因此您必须在活动暂停或销毁时终止它。
您可以查看这里在我的博客文章中,我解释了启动/停止 tcpdump 的整个代码。

I don't understand why, but even with the -l option the buffer is too large if you read on the standard output of the process wherein you run tcpdump.
I solve this problem by redirect TcpDump's output to a file and read this file in another thread. The TcpDump command should be something like :

tcpdump -l-A -s0 > /data/local/output.txt

The run method inside your thread have to be change to read in the output file :

File dumpedFile = new File("/data/local/output.txt");
//open a reader on the tcpdump output file
BufferedReader reader = new BufferedReader(new FileReader(dumpedFile));
String temp = new String();
//The while loop is broken if the thread is interrupted   
while (!Thread.interrupted()) {    
    temp = reader.readLine();
    if (temp!=null) {
        Log.e("READER",new String(temp));    
    }
}

I dont exactly know what you want to do with grep but I think it's possible do achieve the same actions with a regexp inside the Java code.

You should also be aware that the TcpDump's process will never end, so you have to kill it when your activity is paused or distroy.
You can have a look here to my blog post, I explain my whole code to start/stop tcpdump.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文