几年前做的,通过网卡抓包实现网站访问量,栏目,子栏目,文章点击量统计,记录备忘
主类
public class PortalNetSniffer { public static String ModuleID = "PortalNetSniffer"; public static void main(String[] args) { try { String host = "119.87.244.xxx;iread.com.cn"; int port = 80; if(args.length > 0) { ModuleID = args[0]; Mutex mutex = Mutex.read(); mutex.listen(); } if(args.length > 1) { host = args[1]; } if(args.length > 2) { //监听端口 String _port = args[2]; if(Tools.isNumeric(_port)) { port = Integer.valueOf(_port); } } //启动日志管理器 Log.getInstance().setSubroot(ModuleID); Log.getInstance().setDebug(true); Log.getInstance().setLogable(true); Log.getInstance().start(); final NetworkInterface devices[] = JpcapCaptor.getDeviceList(); for(int i = 0; i < devices.length; i++) { NetworkInterface ni = devices[i]; JpcapCaptor jpcap = JpcapCaptor.openDevice(ni, 2000, true, 20); startCapThread(jpcap,host,port); Log.msg("开始抓取第" + i + "个卡口上的数据"); } } catch(Exception e) { Log.err("启动抓包线程失败:"); } } private static void startCapThread(final JpcapCaptor jpcap,final String host,final int port) { Runnable runner = new Runnable() { public void run() { PortalPacketReceiver receiver = new PortalPacketReceiver(host,port); new Thread(receiver).start(); jpcap.loopPacket(-1, receiver); } }; new Thread(runner).start(); } }
主要干活的类
public class PortalPacketReceiver implements PacketReceiver,Runnable { private String HOST = "119.87.xxx.xxx;iread.xxx.cn"; private int PORT = 80; private List<?> validLinks = new ArrayList<String>(); private _MemberClickDao _memberClickDao = null; private Queue<com.monitor.vo.Packet> data = new LinkedList<com.monitor.vo.Packet>(); public PortalPacketReceiver(String host,int port) { this.HOST = host; this.PORT = port; File file = new File(ConfigUtil.getWorkPath(),"config"); file = new File(file,"validLink"); try { validLinks = FileUtils.readLines(file); } catch (IOException e) { e.printStackTrace(); } } public void receivePacket(Packet packet) { //只处理TCP包 if(packet instanceof jpcap.packet.TCPPacket) { TCPPacket p = (TCPPacket)packet; String s = "TCPPacket:| dst_ip " + p.dst_ip + ":" + p.dst_port + "|src_ip " + p.src_ip + ":" + p.src_port + " |len: " + p.len; //log.info(s); //只处理特定端口的包 if(p.dst_port == PORT) { try { if(p.data != null && p.data.length > 0) { com.monitor.vo.Packet pk = new com.monitor.vo.Packet(); pk.setSrcIp(p.src_ip.getHostAddress()); pk.setSrcPort(p.src_port); pk.setDstPort(p.dst_port); pk.setData(new String(p.data)); synchronized(this) { data.offer(pk); this.notify(); } } } catch(Exception e) { Log.err("Error to handle packet"); } } } //凌晨2点30,下班休息一分钟 Calendar now = Calendar.getInstance(Locale.CHINA); int hour = now.get(Calendar.HOUR_OF_DAY); int minute = now.get(Calendar.MINUTE); if(hour == 2 && minute == 30) { ConnectionPool.disconnect(); Log.getInstance().close(); System.exit(0); } } public void run() { //启动数据库连接管理 String serverHost = ConfigUtil.getString( "serverHost" ); String dbType = ConfigUtil.getString( "dbType" ); String dbName = ConfigUtil.getString( "dbName" ); String dbDriver = ConfigUtil.getString( "dbDriver" ); String dbUser = ConfigUtil.getString( "dbUser" ); String dbPassword = ConfigUtil.getString( "dbPassword" ); try { ConnectionPool.connect(serverHost, dbType, dbName, dbDriver, dbUser, dbPassword ); } catch(Exception e) { System.exit(0); } while(true) { //Log.msg("Handle线程在运行"); try { //log.info("list size = "+data.size()); synchronized(this) { if(data.size() > 0) { //log.info("开始干活"); com.monitor.vo.Packet pk = data.poll(); Log.msg(pk.getData()); if(pk != null) { analysis(pk); } } else { wait(1000); } } } catch (InterruptedException e) { e.printStackTrace(); } } } private synchronized void analysis(com.monitor.vo.Packet data) { try { List<Request> list = new ArrayList<Request>(); String[] packet = data.getData().split("\\n\\s*\r",-1); for(int i = 0; i < packet.length; i++) { packet[i] = packet[i].trim(); if(!packet[i].equals("") && (packet[i].startsWith("GET") || packet[i].startsWith("POST"))) { Request req = new Request(); req.setTime(new Date()); req.setUserIp(data.getSrcIp()); req.setSrcPort(data.getSrcPort()); req.setDstPort(data.getDstPort()); String[] lines = packet[i].split("\r\n"); boolean isValidLink = false; for(int j = 0; j < lines.length; j++) { if(!lines[0].startsWith("GET") && !lines[0].startsWith("POST")) { break; } if(lines[j].startsWith("GET") || lines[i].startsWith("POST")) { String[] mup = lines[j].split(" "); if(mup.length > 0) { String method = mup[0].trim(); req.setMethod(method); } if(mup.length > 1) { String uri = mup[1].trim(); Log.msg("\r\nuri == " + uri); if(uri == null || "".equals(uri) || uri.endsWith("css") || uri.endsWith("js") || uri.endsWith("jpg") || uri.endsWith("png") || uri.endsWith("gif") || uri.endsWith("ico")) { break; } if(uri.equals("/"))break; for(int k = 0; k < validLinks.size(); k++) { if(uri.startsWith(validLinks.get(k).toString())) { isValidLink = true; break; } } if(!isValidLink)break; req.setUri(uri); } if(mup.length > 2) { String protocol = mup[2].trim(); req.setProtocol(protocol); } } else { String[] arc = lines[j].split(":",2); if(arc.length > 1) { String key = arc[0].trim(); String value = arc[1].trim(); if(key.equalsIgnoreCase("Accept")) { req.setAccept(value); } else if(key.equalsIgnoreCase("Referer")) { req.setReferer(value); } else if(key.equalsIgnoreCase("Accept-Language")) { req.setAccept_language(value); } else if(key.equalsIgnoreCase("UA-CPU")) { req.setUa_cpu(value); } else if(key.equalsIgnoreCase("Accept-Encoding")) { req.setAccept_encoding(value); } else if(key.equalsIgnoreCase("If-Modified-Since")) { req.setIf_modified_since(value); } else if(key.equalsIgnoreCase("If-None-Match")) { req.setIf_none_match(value); } else if(key.equalsIgnoreCase("User-Agent")) { if(value != null) { //爬虫滚蛋 if(value.indexOf("spider") != -1 || value.indexOf("Googlebot") != -1) { break; } } req.setUser_agent(value); } else if(key.equalsIgnoreCase("Host")) { if(value == null || "".equals(value) || HOST.indexOf(value) == -1) { break; } req.setHost(value); } else if(key.equalsIgnoreCase("Connection")) { req.setConnection(value); } else if(key.equalsIgnoreCase("Cookie")) { req.setCookie(value); } else if(key.equalsIgnoreCase("x-up-calling-line-id")) { if(value.startsWith("861") && value.length() ==13) { value = value.substring(2); } if(value.startsWith("+861") && value.length() == 14) { value = value.substring(3); } Log.msg("\r\nmobile ="+value); req.setMobile(value); } } } } if(req.getUri()!=null && !req.getUri().equals("") && !req.getUri().equals("/")) list.add(req); } } //下面进行分析,太长,略... } catch(Exception e) { Log.err("解析包异常:",e.getMessage()); } } }