갑자기 코드프로젝트에서 눈에 띄어서 번역한 글을 보다가..
자바도 pcap 같은 라이브러리가 있을 것 같아서 찾아 보았습니다.
가장 눈에 띄는 링크를 클릭 해 보았더니,
https://www.codewithc.com/network-packet-sniffer-java-project/
궁금증이 생겨서 그냥 이클립스에서 돌려 보았습니다.
돌려보니까 뭐.. 안돌아가네요
고쳐볼까 말까 하다가... 약간의 삽질이면 해볼까 하고 진행해 봅니다.
jpcap 이라는 패키지가 없는 것 보니, 구하긴 해야 할까봐요
소스를 다 이어 붙혀버렸습니다.
아...그리고 나면 이제 네이티브 컴파일이 남겠네요.
그냥 주어진 대로, 32비트로 컴파일 해볼까 합니다. JNI 경로를 내것으로 맞추어 주었습니다.
(JNI가 뭔지 모르신다면... 좀 더 알아보시면 됩니다. )
오류가 납니다. 재 정의 문제가 일어나는 데요...
pcap.h 순서를 다음과 같이 바꾸고
#ifndef lib_pcap_h
#define lib_pcap_h
#include <stdio.h>
#if defined(WIN32)
#include <pcap-stdinc.h>
#elif defined(MSDOS)
#include <sys/types.h>
#include <sys/socket.h> /* u_int, u_char etc. */
#else /* UN*X */
#include <sys/types.h>
#include <sys/time.h>
#endif /* WIN32/MSDOS/UN*X */
#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
#include <pcap-bpf.h>
#endif
/*#include <stdio.h>*/
pcap-stdinc.h 헤더 파일을 다음과 같이 바꿔 주었습니다.
#ifndef vsnprintf
#define snprintf _snprintf
#endif
#ifndef vsnprintf
#define vsnprintf _vsnprintf
#endif
그런다음에 빌드 해 줍니다. 그러면 다음 디렉토리에 Jpcap.dll 이 생기게 되죠...
이게 끝이라면, 삽질이라고 하지는 않았겠죠? 이제부터 시작이라고 말은 못해도 뭐 여하튼..
다시 자바로 돌아가서 위 dll 을 맞춰 볼 시간 입니다.
위 dll 을 자바로 넣어 볼려면 혹은 구동 해 볼려면, 다음의 링크에 소스코드를 얻어 와야 합니다.
https://blog.naver.com/tommybee/221998813223
메인 메서드가 아래 처럼 변해야 겠죠...
public static void main(String[] args){
try{
//둘 중 하나만 쓰면 됩니다.
//setLibraryPath("C:/DEV/LIBS/jpcap-master/src/c/win32/Release/");
addLibraryPath("C:/DEV/LIBS/jpcap-master/src/c/win32/Release/");
//System.setProperty("java.library.path", "C:/DEV/LIBS/jpcap-master/src/c/win32/Release/");
System.loadLibrary("Jpcap");
}catch(Exception e){
JOptionPane.showMessageDialog(null,"Cannot find Jpcap. Please download and install Jpcap before running.");
System.exit(0);
}
try{
Class<?> c=Class.forName("jpcap.JpcapCaptor");
}catch(ClassNotFoundException e){
JOptionPane.showMessageDialog(null,"Cannot find Jpcap. Please download and install Jpcap before running.");
System.exit(0);
}
PacketAnalyzerLoader.loadDefaultAnalyzer();
StatisticsTakerLoader.loadStatisticsTaker();
loadProperty();
openNewWindow();
}
그러고 나면, 다음 오류가 나고 있네요...ㅡ.ㅡ;;
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\DEV\LIBS\jpcap-master\src\c\win32\Release\Jpcap.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2430)
at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2487)
at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2684)
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2649)
at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:827)
at java.base/java.lang.System.loadLibrary(System.java:1871)
at netpacsniff.NetPackSniff.main(NetPackSniff.java:75)
와우~ 멋지네요.. 다시 C로 돌아가야 하나요???
아니면, 32비트 용으로 자바를 다시 받는 것도 되겠지만...
검색이 최고 겠죠? 감사의 편지라도 써야 할 것 같아요...
이 글 처음으로 돌아가서 다시 초심으로 여기까지 오면 될 것 같습니다.
메인 메서드 소스를 다시 맞추고...
try{
//setLibraryPath("C:\\DEV\\LIBS\\jpcap-x64-master\\src\\c\\win32\\x64\\Release\\");
addLibraryPath("C:\\DEV\\LIBS\\jpcap-x64-master\\src\\c\\win32\\x64\\Release\\");
//System.setProperty("java.library.path", "C:/DEV/LIBS/jpcap-master/src/c/win32/Release/");
System.loadLibrary("Jpcap");
}catch(Exception e){
JOptionPane.showMessageDialog(null,"Cannot find Jpcap. Please download and install Jpcap before running.");
System.exit(0);
}
다시 진행을 해보면, 다음과 같이 GUI 뜨는 것을 확인 해 볼 수 있습니다.
잘 모르면 젤 눈에 띄는 화살표를 한번 눌러볼까요
뭔지 모르겠지만, 사람의 호기심을 자극하는 화면이 뜨네요...
내 네트워크 카드를 선택하고 나서
OK 하면...ㅎㅎㅎ 또 오류가 나네요
setPacketValue 라...
혹시 뭔가 잘 못 되었나 싶어서 콘솔 프로그램을 하나 참고를 해봤으나,
JpcapCaptor captor;
NetworkInterface[] list;
String str,info;
int x, nChoice;
int nCountPacket = 0;
public static void main(String args[]) {
try{
//NetPackSniff.setLibraryPath("C:\\DEV\\LIBS\\jpcap-x64-master\\src\\c\\win32\\x64\\Release\\");
NetPackSniff.addLibraryPath("C:\\DEV\\LIBS\\jpcap-x64-master\\src\\c\\win32\\x64\\Release\\");
//System.setProperty("java.library.path", "C:/DEV/LIBS/jpcap-master/src/c/win32/Release/");
System.loadLibrary("Jpcap");
}catch(Exception e){
JOptionPane.showMessageDialog(null,"Cannot find Jpcap. Please download and install Jpcap before running.");
System.exit(0);
}
new NetPackSniffConsole();
}
public NetPackSniffConsole()
{
list = JpcapCaptor.getDeviceList();
System.out.println("Available interfaces: ");
for(x=0; x<list.length; x++) {
System.out.println(x+" -> "+list[x].description);
}
System.out.println("-------------------------\n");
nChoice = Integer.parseInt(getInput("Choose interface (0,1..): "));
System.out.println("Listening on interface -> "+list[nChoice].description);
System.out.println("-------------------------\n");
/*Setup device listener */
try {
captor=JpcapCaptor.openDevice(list[nChoice], 65535, false, 20);
/* listen for TCP/IP only */
captor.setFilter("ip and tcp", true);
} catch(IOException ioe) { ioe.printStackTrace(); }
/* start listening for packets */
while (true) {
Packet info = captor.getPacket();
if(info != null){
String sData = getPacketText(info);
System.out.print(sData);
}
}
}
/* get user input */
public static String getInput(String q)
{
String input = "";
System.out.print(q);
BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in));
try {
input = bufferedreader.readLine();
} catch(IOException ioexception) { }
return input;
}
/* return packet data in true text */
String getPacketText(Packet pack)
{
int i=0,j=0;
// Data (Payload)만 출력
byte[] bytes=new byte[pack.data.length];
System.arraycopy(pack.data, 0, bytes, 0, pack.data.length);
//--------------------------------------------------------------------
// 캐스팅한번하면 Packet 클래스가 깨진다. 왜그런지는 모르겠다. --> 패키지특징내지 버그같음..
//--------------------------------------------------------------------
String sPackInfo = "";
if( pack.data.length > 0){
sPackInfo = "SRC:" + ((IPPacket)pack).src_ip + "\r\n" + "DST:" + ( (IPPacket)pack).dst_ip;
sPackInfo += "\r\n" + ShowHex(bytes.length, bytes);
}
return sPackInfo;
}
// Hex 출력
private String ShowHex(int nSize, byte[] pData)
{
final int DISPLAY_COUNT = 16;
final int MAX_SIZE = 1024 * 15; // 최대보여지는개수
String msg = "";
String sTmp = "";
String sTmp2 = "";
String sLineNum = "";
int nLineNum = 0;
msg = "0000:";
if(nSize > MAX_SIZE) nSize = MAX_SIZE;
for(int i = 1; i < nSize + 1; i++){
sTmp = sTmp.format("%02X ", pData[ i - 1 ] );
if(( pData[ i - 1] < 127) && ( pData[ i - 1] > 32)){
sTmp2 += sTmp2.format("%c", pData[ i - 1 ] );
} else {
sTmp2 += ".";
}
if(i % DISPLAY_COUNT == 0 && i != 1){
msg += sTmp;
msg += " ";
msg += sTmp2;
msg += "\r\n";
sTmp2 = "";
msg += sLineNum.format("%04X:", nLineNum += DISPLAY_COUNT);
} else if(i == nSize && i % DISPLAY_COUNT != 0 ){
int nEmtSpace = DISPLAY_COUNT - (i % DISPLAY_COUNT);
for(int j = 0; j < nEmtSpace; j++){
sTmp += " ";
}
msg += sTmp;
msg += " ";
msg += sTmp2;
msg += "\r\n";
} else {
msg += sTmp;
}
}
if ( nSize == 0 ) msg = "";
return msg;
}
똑같은 오류 메시지를 뱉고 있네요...
음... 그래서 머리로 생각을 좀 해보기로 했죠.
메서드가 없다는 것은 C 에서 호출 한 것이겠구나 하고요. 해당 이름으로 찾아 보니 다음과 같은 인터페이스가 있네요
setPacketValueMID=(*env)->GetMethodID(env,Packet,"setPacketValue",
"(JJII)V");
Packet 은 다음과 같이 정의 하였네요
GlobalClassRef(Packet,"jpcap/packet/Packet");
그리고 해당 메서드를 자바에서 찾아보면,
void setPacketValue(long sec, long usec, int caplen, int len, int processid, String process) {
this.sec = sec;
this.usec = usec;
this.caplen = caplen;
this.len = len;
this.processid = processid;
this.process = process;
}
위와 같이 하나가 존재 합니다. 그래서 보면 시그너쳐가 틀려 보인다는 것이죠.
https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html
아래 시그너쳐의 변환은
"(JJII)V" ==> (long, long, int, int )
인 반환값이 없는 메서드가 되겠죠. 그럼 위에 메서드를 하나 복사해서 다음과 같이 만들어 보겠습니다. 수정 하는 것은 능력도 안되고 귀찮기도 하고 그리고 개발자의 의도도 잘 모르겠네요...
코드로 보아 프로세스 아이디랑 프로세스를 찾을려고 했던 것 같은데 음...과연 그럴까 싶기도하고요.
void setPacketValue(long sec, long usec, int caplen, int len) {
this.sec = sec;
this.usec = usec;
this.caplen = caplen;
this.len = len;
this.processid = 0;
this.process = "N/A";
}
그럼 부푼 꿈을 안고 다시 실행 시켜봅니다. 그런데 가만 생각해 보니 우리집에서 Wi-Fi 를 사용하고 있다는 것을 깜박했네요^^;;
Microsoft 가 세개, 랜카드가 한개가 나오네요
내 컴터의 네트워크는...이렇게 되어 있습니다.
그래서 아무 Microsoft 를 눌러 보았어요.
음... 무엇을 표현하려고 했는 지는 소스를 찬찬히 띁어 보아야 하겠네요.
원래 사이트의 이미지는 이런 것이었는 데...
현실과 이상의 차이가 넘 크네요...
위에서 언급한 콘솔 프로그램은 나오질 않는 거 보니 API가 약간 바뀐듯 하네요...
정신 건강에 안좋으니 그만 접어야 할 것 같습니다.
잘 된 것도 아니고, 안 된것도 아니고 ... 찝찝하네요~^^;;
그렇다고 남의 작품을 나쁘다고 하는 것은 아니고, 네트워크에 대해서 깊숙히 알지 못해서 나온 얘기라고 생각 해 주세요~
이상.
부록. jpacp64비트 dll과 소스코드
'프로그래밍' 카테고리의 다른 글
fabs, abs, sprintf, format (1) | 2022.12.27 |
---|---|
Hello World: C, 어셈블리, 오브젝트 파일 그리고 실행파일 (0) | 2022.12.26 |
[Java] DTO (Data Transfer Object) (0) | 2022.12.24 |
[Java]문자 반복 찾기 없이 가장 긴 하위 문자열 찾기 (0) | 2022.12.21 |
[C] 포인터와 구조체 (0) | 2022.12.18 |