ReadLine в TCPDump-Buffer иногда блокируется, пока не убьется tcpdump

У меня проблема с использованием TCPDump из моего Android-приложения. Предполагается, что строка tcpdump будет читать строку за строкой и обрабатывать ее в моем приложении.
Проблема в:
Иногда код работает нормально, он сразу читает захваченные пакеты. Но иногда ReadLine блокируется, пока я не уничтожу процесс tcpdump из консоли Linux (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);
            }

        }

    }

}

}

2 ответа

Поскольку выходные данные, отправляемые в каналы, обычно буферизируются в 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";

Я не понимаю, почему, но даже с опцией -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, но я думаю, что возможно выполнить те же действия с помощью регулярного выражения в коде Java.

Вы также должны знать, что процесс TcpDump никогда не закончится, поэтому вы должны убить его, когда ваша активность приостановлена ​​или нарушена. Вы можете посмотреть здесь на мой пост в блоге, я объясняю весь мой код для запуска / остановки tcpdump.

Другие вопросы по тегам