ReadLine on TCPDump-Buffer sometimes blocks until kill tcpdump

倾然丶 夕夏残阳落幕 提交于 2020-01-03 02:05:25

问题


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

        }

    }

}

}


回答1:


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";



回答2:


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.



来源:https://stackoverflow.com/questions/5714875/readline-on-tcpdump-buffer-sometimes-blocks-until-kill-tcpdump

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!