问题描述
||
我在Android应用程序中使用TCPDump时遇到问题。
它应该逐行读取tcpdump的输出并在我的Application中处理它。问题是:有时代码可以正常工作,它会立即读取捕获的数据包。但是有时,ReadLine会阻塞,直到我从Linux控制台(killall tcpdump)中杀死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);
}
}
}
}
}解决方法
因为发送到管道的输出通常是块缓冲的,所以
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代码中的regexp可以实现相同的操作。
您还应该知道,TcpDump的进程将永远不会结束,因此当您的活动被暂停或破坏时,您必须将其杀死。
您可以在这里查看我的博客文章,我解释了我的整个代码来启动/停止tcpdump。