开发者

ReadLine on TCPDump-Buffer sometimes blocks until kill tcpdump

开发者 https://www.devze.com 2023-02-27 04:14 出处:网络
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 f

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_CO开发者_运维知识库MMAND = "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);
            }

        }

    }

}

}


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消