libpcap的使用

Python Scapy工具-sniff函数 Scapy 是适用于 Python 的一个快速、高层次的屏幕抓取和 web 抓取框架,用于抓取 web站点并从页面中提取结构化的数据。 Scapy可以轻松地处理扫描(Scanning)、路由跟踪(Tracerouting)、探测(Probing)、单元测试(Unit Tests)、攻击(Attacks)和发现网络(Network Discorvery)之类的传统任务。 Scapy的安装如下: 通过cmd命令:pip install scapy 进行安装 sniff函数及其参数如下: sniff(count= 阅读详情
libpcap的使用



libpcap是一个网络数据包捕获函数库,功能非常强大,Linux下著名的tcpdump就是以它为基础的。今天我们利用它来完成一个我们自己的网络嗅探器(sniffer)




首先先介绍一下本次实验的环境:
Ubuntu 11.04,IP:192.168.1.1,广播地址:192.168.1.255,子网掩码:255.255.255.0
可以使用下面的命令设置:
sudo ifconfig eth0 192.168.1.1 broadcast 192.168.1.255 netmask 255.255.255.0





1.安装
在http://www.tcpdump.org/下载libpcap(tcpdump的源码也可以从这个网站下载)
解压
./configure
make
sudo make install





2.使用
安装好libpcap后,我们要使用它啦,先写一个简单的程序,并介绍如何使用libpcap库编译它:
Makefile:
  1. all: test.c
  2. gcc -g -Wall -o test test.c -lpcap
  3. clean:
  4. rm -rf *.o test
all: test.c
	gcc -g -Wall -o test test.c -lpcap

clean:
	rm -rf *.o test

其后的程序的Makefile均类似,故不再重复


test1.c
  1. #include <pcap.h>
  2. #include <stdio.h>
  3. int main()
  4. {
  5. char errBuf[PCAP_ERRBUF_SIZE], * device;
  6. device = pcap_lookupdev(errBuf);
  7. if(device)
  8. {
  9. printf("success: device: %s\n", device);
  10. }
  11. else
  12. {
  13. printf("error: %s\n", errBuf);
  14. }
  15. return 0;
  16. }
#include <pcap.h>
#include <stdio.h>

int main()
{
  char errBuf[PCAP_ERRBUF_SIZE], * device;
  
  device = pcap_lookupdev(errBuf);
  
  if(device)
  {
    printf("success: device: %s\n", device);
  }
  else
  {
    printf("error: %s\n", errBuf);
  }
  
  return 0;
}





可以成功编译,不过运行的时候却提示找不到libpcap.so.1,因为libpcap.so.1默认安装到了/usr/local/lib下,我们做一个符号链接到/usr/lib/下即可:






运行test的时候输出"no suitable device found",原因是我们没有以root权限运行,root权限运行后就正常了:







下面开始正式讲解如何使用libpcap:
首先要使用libpcap,我们必须包含pcap.h头文件,可以在/usr/local/include/pcap/pcap.h找到,其中包含了每个类型定义的详细说明。




1.获取网络接口
首先我们需要获取监听的网络接口:
我们可以手动指定或让libpcap自动选择,先介绍如何让libpcap自动选择:
char * pcap_lookupdev(char * errbuf)
上面这个函数返回第一个合适的网络接口的字符串指针,如果出错,则errbuf存放出错信息字符串,errbuf至少应该是PCAP_ERRBUF_SIZE个字节长度的。注意,很多libpcap函数都有这个参数。
pcap_lookupdev()一般可以在跨平台的,且各个平台上的网络接口名称都不相同的情况下使用。
如果我们手动指定要监听的网络接口,则这一步跳过,我们在第二步中将要监听的网络接口字符串硬编码在pcap_open_live里。




2.释放网络接口
在操作为网络接口后,我们应该要释放它:
void pcap_close(pcap_t * p)
该函数用于关闭pcap_open_live()获取的pcap_t的网络接口对象并释放相关资源。




3.打开网络接口
获取网络接口后,我们需要打开它:
pcap_t * pcap_open_live(const char * device, int snaplen, int promisc, int to_ms, char * errbuf)
上面这个函数会返回指定接口的pcap_t类型指针,后面的所有操作都要使用这个指针。
第一个参数是第一步获取的网络接口字符串,可以直接使用硬编码。
第二个参数是对于每个数据包,从开头要抓多少个字节,我们可以设置这个值来只抓每个数据包的头部,而不关心具体的内容。典型的以太网帧长度是1518字节,但其他的某些协议的数据包会更长一点,但任何一个协议的一个数据包长度都必然小于65535个字节。
第三个参数指定是否打开混杂模式(Promiscuous Mode),0表示非混杂模式,任何其他值表示混合模式。如果要打开混杂模式,那么网卡必须也要打开混杂模式,可以使用如下的命令打开eth0混杂模式:
ifconfig eth0 promisc
第四个参数指定需要等待的毫秒数,超过这个数值后,第3步获取数据包的这几个函数就会立即返回。0表示一直等待直到有数据包到来。
第五个参数是存放出错信息的数组。




4.获取数据包
打开网络接口后就已经开始监听了,那如何知道收到了数据包呢?有下面3种方法:
a)
u_char * pcap_next(pcap_t * p, struct pcap_pkthdr * h)
如果返回值为NULL,表示没有抓到包
第一个参数是第2步返回的pcap_t类型的指针
第二个参数是保存收到的第一个数据包的pcap_pkthdr类型的指针
pcap_pkthdr类型的定义如下:
  1. struct pcap_pkthdr
  2. {
  3. struct timeval ts; /* time stamp */
  4. bpf_u_int32 caplen; /* length of portion present */
  5. bpf_u_int32 len; /* length this packet (off wire) */
  6. };
struct pcap_pkthdr
{
  struct timeval ts;    /* time stamp */
  bpf_u_int32 caplen;   /* length of portion present */
  bpf_u_int32 len;      /* length this packet (off wire) */
};

注意这个函数只要收到一个数据包后就会立即返回


b)
int pcap_loop(pcap_t * p, int cnt, pcap_handler callback, u_char * user)
第一个参数是第2步返回的pcap_t类型的指针
第二个参数是需要抓的数据包的个数,一旦抓到了cnt个数据包,pcap_loop立即返回。负数的cnt表示pcap_loop永远循环抓包,直到出现错误。
第三个参数是一个回调函数指针,它必须是如下的形式:
void callback(u_char * userarg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
第一个参数是pcap_loop的最后一个参数,当收到足够数量的包后pcap_loop会调用callback回调函数,同时将pcap_loop()的user参数传递给它
第二个参数是收到的数据包的pcap_pkthdr类型的指针
第三个参数是收到的数据包数据




c)
int pcap_dispatch(pcap_t * p, int cnt, pcap_handler callback, u_char * user)

这个函数和pcap_loop()非常类似,只是在超过to_ms毫秒后就会返回(to_ms是pcap_open_live()的第4个参数)


例子:

test2:

  1. #include <pcap.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. int main()
  6. {
  7. char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  8. /* get a device */
  9. devStr = pcap_lookupdev(errBuf);
  10. if(devStr)
  11. {
  12. printf("success: device: %s\n", devStr);
  13. }
  14. else
  15. {
  16. printf("error: %s\n", errBuf);
  17. exit(1);
  18. }
  19. /* open a device, wait until a packet arrives */
  20. pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
  21. if(!device)
  22. {
  23. printf("error: pcap_open_live(): %s\n", errBuf);
  24. exit(1);
  25. }
  26. /* wait a packet to arrive */
  27. struct pcap_pkthdr packet;
  28. const u_char * pktStr = pcap_next(device, &packet);
  29. if(!pktStr)
  30. {
  31. printf("did not capture a packet!\n");
  32. exit(1);
  33. }
  34. printf("Packet length: %d\n", packet.len);
  35. printf("Number of bytes: %d\n", packet.caplen);
  36. printf("Recieved time: %s\n", ctime((consttime_t *)&packet.ts.tv_sec));
  37. pcap_close(device);
  38. return 0;
  39. }
#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
  char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  
  /* get a device */
  devStr = pcap_lookupdev(errBuf);
  
  if(devStr)
  {
    printf("success: device: %s\n", devStr);
  }
  else
  {
    printf("error: %s\n", errBuf);
    exit(1);
  }
  
  /* open a device, wait until a packet arrives */
  pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
  
  if(!device)
  {
    printf("error: pcap_open_live(): %s\n", errBuf);
    exit(1);
  }

  /* wait a packet to arrive */
  struct pcap_pkthdr packet;
  const u_char * pktStr = pcap_next(device, &packet);

  if(!pktStr)
  {
    printf("did not capture a packet!\n");
    exit(1);
  }
  
  printf("Packet length: %d\n", packet.len);
  printf("Number of bytes: %d\n", packet.caplen);
  printf("Recieved time: %s\n", ctime((const time_t *)&packet.ts.tv_sec)); 
  
  pcap_close(device);
  
  return 0;
}






打开两个终端,先ping 192.168.1.10,由于我们的ip是192.168.1.1,因此我们可以收到广播的数据包,另一个终端运行test,就会抓到这个包。







下面的这个程序会把收到的数据包内容全部打印出来,运行方式和上一个程序一样:
test3:
  1. #include <pcap.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
  6. {
  7. int * id = (int *)arg;
  8. printf("id: %d\n", ++(*id));
  9. printf("Packet length: %d\n", pkthdr->len);
  10. printf("Number of bytes: %d\n", pkthdr->caplen);
  11. printf("Recieved time: %s", ctime((consttime_t *)&pkthdr->ts.tv_sec));
  12. int i;
  13. for(i=0; i<pkthdr->len; ++i)
  14. {
  15. printf(" %02x", packet[i]);
  16. if( (i + 1) % 16 == 0 )
  17. {
  18. printf("\n");
  19. }
  20. }
  21. printf("\n\n");
  22. }
  23. int main()
  24. {
  25. char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  26. /* get a device */
  27. devStr = pcap_lookupdev(errBuf);
  28. if(devStr)
  29. {
  30. printf("success: device: %s\n", devStr);
  31. }
  32. else
  33. {
  34. printf("error: %s\n", errBuf);
  35. exit(1);
  36. }
  37. /* open a device, wait until a packet arrives */
  38. pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
  39. if(!device)
  40. {
  41. printf("error: pcap_open_live(): %s\n", errBuf);
  42. exit(1);
  43. }
  44. /* wait loop forever */
  45. int id = 0;
  46. pcap_loop(device, -1, getPacket, (u_char*)&id);
  47. pcap_close(device);
  48. return 0;
  49. }
#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>

void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
  int * id = (int *)arg;
  
  printf("id: %d\n", ++(*id));
  printf("Packet length: %d\n", pkthdr->len);
  printf("Number of bytes: %d\n", pkthdr->caplen);
  printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); 
  
  int i;
  for(i=0; i<pkthdr->len; ++i)
  {
    printf(" %02x", packet[i]);
    if( (i + 1) % 16 == 0 )
    {
      printf("\n");
    }
  }
  
  printf("\n\n");
}

int main()
{
  char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  
  /* get a device */
  devStr = pcap_lookupdev(errBuf);
  
  if(devStr)
  {
    printf("success: device: %s\n", devStr);
  }
  else
  {
    printf("error: %s\n", errBuf);
    exit(1);
  }
  
  /* open a device, wait until a packet arrives */
  pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
  
  if(!device)
  {
    printf("error: pcap_open_live(): %s\n", errBuf);
    exit(1);
  }
  
  /* wait loop forever */
  int id = 0;
  pcap_loop(device, -1, getPacket, (u_char*)&id);
  
  pcap_close(device);

  return 0;
}






从上图可以看出,如果我们没有按Ctrl+c,test会一直抓到包,因为我们将pcap_loop()设置为永远循环




由于ping属于icmp协议,并且发出icmp协议数据包之前必须先通过arp协议获取目的主机的mac地址,因此我们抓到的包是arp协议的,而arp协议的数据包长度正好是42字节(14字节的以太网帧头+28字节的arp数据)。具体内容请参考相关网络协议说明。






5.分析数据包
我们既然已经抓到数据包了,那么我们要开始分析了,这部分留给读者自己完成,具体内容可以参考相关的网络协议说明。在本文的最后,我会示范性的写一个分析arp协议的sniffer,仅供参考。要特别注意一点,网络上的数据是网络字节顺序的,因此分析前需要转换为主机字节顺序(ntohs()函数)。




6.过滤数据包
我们抓到的数据包往往很多,如何过滤掉我们不感兴趣的数据包呢?
几乎所有的操作系统(BSD, AIX, Mac OS, Linux等)都会在内核中提供过滤数据包的方法,主要都是基于BSD Packet Filter(BPF)结构的。libpcap利用BPF来过滤数据包。
过滤数据包需要完成3件事:
a) 构造一个过滤表达式
b) 编译这个表达式
c) 应用这个过滤器



a)

BPF使用一种类似于汇编语言的语法书写过滤表达式,不过libpcap和tcpdump都把它封装成更高级且更容易的语法了,具体可以man tcpdump,以下是一些例子:
src host 192.168.1.177
只接收源ip地址是192.168.1.177的数据包


dst port 80
只接收tcp/udp的目的端口是80的数据包


not tcp
只接收不使用tcp协议的数据包


tcp[13] == 0x02 and (dst port 22 or dst port 23)
只接收SYN标志位置位且目标端口是22或23的数据包(tcp首部开始的第13个字节)


icmp[icmptype] == icmp-echoreply or icmp[icmptype] == icmp-echo
只接收icmp的ping请求和ping响应的数据包


ehter dst 00:e0:09:c1:0e:82
只接收以太网mac地址是00:e0:09:c1:0e:82的数据包


ip[8] == 5
只接收ip的ttl=5的数据包(ip首部开始的第8个字节)


b)
构造完过滤表达式后,我们需要编译它,使用如下函数:
int pcap_compile(pcap_t * p, struct bpf_program * fp, char * str, int optimize, bpf_u_int32 netmask)
fp:这是一个传出参数,存放编译后的bpf
str:过滤表达式
optimize:是否需要优化过滤表达式
metmask:简单设置为0即可


c)
最后我们需要应用这个过滤表达式:
int pcap_setfilter(pcap_t * p, struct bpf_program * fp)
第二个参数fp就是前一步pcap_compile()的第二个参数




应用完过滤表达式之后我们便可以使用pcap_loop()或pcap_next()等抓包函数来抓包了。


下面的程序演示了如何过滤数据包,我们只接收目的端口是80的数据包:
test4.c
  1. #include <pcap.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
  6. {
  7. int * id = (int *)arg;
  8. printf("id: %d\n", ++(*id));
  9. printf("Packet length: %d\n", pkthdr->len);
  10. printf("Number of bytes: %d\n", pkthdr->caplen);
  11. printf("Recieved time: %s", ctime((consttime_t *)&pkthdr->ts.tv_sec));
  12. int i;
  13. for(i=0; i<pkthdr->len; ++i)
  14. {
  15. printf(" %02x", packet[i]);
  16. if( (i + 1) % 16 == 0 )
  17. {
  18. printf("\n");
  19. }
  20. }
  21. printf("\n\n");
  22. }
  23. int main()
  24. {
  25. char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  26. /* get a device */
  27. devStr = pcap_lookupdev(errBuf);
  28. if(devStr)
  29. {
  30. printf("success: device: %s\n", devStr);
  31. }
  32. else
  33. {
  34. printf("error: %s\n", errBuf);
  35. exit(1);
  36. }
  37. /* open a device, wait until a packet arrives */
  38. pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
  39. if(!device)
  40. {
  41. printf("error: pcap_open_live(): %s\n", errBuf);
  42. exit(1);
  43. }
  44. /* construct a filter */
  45. struct bpf_program filter;
  46. pcap_compile(device, &filter, "dst port 80", 1, 0);
  47. pcap_setfilter(device, &filter);
  48. /* wait loop forever */
  49. int id = 0;
  50. pcap_loop(device, -1, getPacket, (u_char*)&id);
  51. pcap_close(device);
  52. return 0;
  53. }
#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>

void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
  int * id = (int *)arg;
  
  printf("id: %d\n", ++(*id));
  printf("Packet length: %d\n", pkthdr->len);
  printf("Number of bytes: %d\n", pkthdr->caplen);
  printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); 
  
  int i;
  for(i=0; i<pkthdr->len; ++i)
  {
    printf(" %02x", packet[i]);
    if( (i + 1) % 16 == 0 )
    {
      printf("\n");
    }
  }
  
  printf("\n\n");
}

int main()
{
  char errBuf[PCAP_ERRBUF_SIZE], * devStr;
  
  /* get a device */
  devStr = pcap_lookupdev(errBuf);
  
  if(devStr)
  {
    printf("success: device: %s\n", devStr);
  }
  else
  {
    printf("error: %s\n", errBuf);
    exit(1);
  }
  
  /* open a device, wait until a packet arrives */
  pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
  
  if(!device)
  {
    printf("error: pcap_open_live(): %s\n", errBuf);
    exit(1);
  }
  
  /* construct a filter */
  struct bpf_program filter;
  pcap_compile(device, &filter, "dst port 80", 1, 0);
  pcap_setfilter(device, &filter);
  
  /* wait loop forever */
  int id = 0;
  pcap_loop(device, -1, getPacket, (u_char*)&id);
  
  pcap_close(device);

  return 0;
}




在下面的这一个例子中,客户机通过tcp的9732端口连接服务器,发送字符'A',之后服务器将'A'+1即'B'返回给客户机,具体实现可以参考:http://blog.youkuaiyun.com/htttw/article/details/7519964


服务器的ip是192.168.56.101,客户机的ip是192.168.56.1
服务器:



Makefile:

  1. all: tcp_client.c tcp_server.c
  2. gcc -g -Wall -o tcp_client tcp_client.c
  3. gcc -g -Wall -o tcp_server tcp_server.c
  4. clean:
  5. rm -rf *.o tcp_client tcp_server
all: tcp_client.c tcp_server.c
	gcc -g -Wall -o tcp_client tcp_client.c
	gcc -g -Wall -o tcp_server tcp_server.c

clean:
	rm -rf *.o tcp_client tcp_server


tcp_server:

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <arpa/inet.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #define PORT 9832
  9. #define SERVER_IP "192.168.56.101"
  10. int main()
  11. {
  12. /* create a socket */
  13. int server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
  14. struct sockaddr_in server_addr;
  15. server_addr.sin_family = AF_INET;
  16. server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
  17. server_addr.sin_port = htons(PORT);
  18. /* bind with the local file */
  19. bind(server_sockfd, (struct sockaddr *)&server_addr,sizeof(server_addr));
  20. /* listen */
  21. listen(server_sockfd, 5);
  22. char ch;
  23. int client_sockfd;
  24. struct sockaddr_in client_addr;
  25. socklen_t len = sizeof(client_addr);
  26. while(1)
  27. {
  28. printf("server waiting:\n");
  29. /* accept a connection */
  30. client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len);
  31. /* exchange data */
  32. read(client_sockfd, &ch, 1);
  33. printf("get char from client: %c\n", ch);
  34. ++ch;
  35. write(client_sockfd, &ch, 1);
  36. /* close the socket */
  37. close(client_sockfd);
  38. }
  39. return 0;
  40. }
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define PORT 9832
#define SERVER_IP "192.168.56.101"

int main()
{
  /* create a socket */
  int server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
  
  struct sockaddr_in server_addr;
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
  server_addr.sin_port = htons(PORT);
  
  /* bind with the local file */
  bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
  
  /* listen */
  listen(server_sockfd, 5);
  
  char ch;
  int client_sockfd;
  struct sockaddr_in client_addr;
  socklen_t len = sizeof(client_addr);
  while(1)
  {
    printf("server waiting:\n");
    
    /* accept a connection */
    client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len);
    
    /* exchange data */
    read(client_sockfd, &ch, 1);
    printf("get char from client: %c\n", ch);
    ++ch;
    write(client_sockfd, &ch, 1);
    
    /* close the socket */
    close(client_sockfd);
  }
  
  return 0;
}


tcp_client:

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <arpa/inet.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #define PORT 9832
  9. #define SERVER_IP "192.168.56.101"
  10. int main()
  11. {
  12. /* create a socket */
  13. int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  14. struct sockaddr_in address;
  15. address.sin_family = AF_INET;
  16. address.sin_addr.s_addr = inet_addr(SERVER_IP);
  17. address.sin_port = htons(PORT);
  18. /* connect to the server */
  19. int result = connect(sockfd, (struct sockaddr *)&address,sizeof(address));
  20. if(result == -1)
  21. {
  22. perror("connect failed: ");
  23. exit(1);
  24. }
  25. /* exchange data */
  26. char ch = 'A';
  27. write(sockfd, &ch, 1);
  28. read(sockfd, &ch, 1);
  29. printf("get char from server: %c\n", ch);
  30. /* close the socket */
  31. close(sockfd);
  32. return 0;
  33. }
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define PORT 9832
#define SERVER_IP "192.168.56.101"

int main()
{
  /* create a socket */
  int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  
  struct sockaddr_in address;
  address.sin_family = AF_INET;
  address.sin_addr.s_addr = inet_addr(SERVER_IP);
  address.sin_port = htons(PORT);
  
  /* connect to the server */
  int result = connect(sockfd, (struct sockaddr *)&address, sizeof(address));
  if(result == -1)
  {
    perror("connect failed: ");
    exit(1);
  }
  
  /* exchange data */
  char ch = 'A';
  write(sockfd, &ch, 1);
  read(sockfd, &ch, 1);
  printf("get char from server: %c\n", ch);
  
  /* close the socket */
  close(sockfd);
  
  return 0;
}



运行方法如下,首先在服务器上运行tcp_server,然后运行我们的监听器,然后在客户机上运行tcp_client,注意,我们可以先清空arp缓存,这样就可以看到整个通信过程(包括一开始的arp广播)
在客户机上运行下列命令来清空记录服务器的arp缓存:
sudo arp -d 192.168.56.101
arp -a
后发现已经删除了记录服务器的arp缓存




抓包的结果如下所示,由于包太多了,无法全部截图,因此我把所有内容保存在下面的文本中了:



全部的包如下:

  1. hutao@hutao-VirtualBox:~/test3$ sudo ./test
  2. success: device: eth0
  3. id: 1
  4. Packet length: 60
  5. Number of bytes: 60
  6. Recieved time: Sat Apr 28 19:57:50 2012
  7. ff ff ff ff ff ff 0a 00 27 00 00 00 08 06 00 01
  8. 08 00 06 04 00 01 0a 00 27 00 00 00 c0 a8 38 01
  9. 00 00 00 00 00 00 c0 a8 38 65 00 00 00 00 00 00
  10. 00 00 00 00 00 00 00 00 00 00 00 00
  11. id: 2
  12. Packet length: 42
  13. Number of bytes: 42
  14. Recieved time: Sat Apr 28 19:57:50 2012
  15. 0a 00 27 00 00 00 08 00 27 9c ff b1 08 06 00 01
  16. 08 00 06 04 00 02 08 00 27 9c ff b1 c0 a8 38 65
  17. 0a 00 27 00 00 00 c0 a8 38 01
  18. id: 3
  19. Packet length: 74
  20. Number of bytes: 74
  21. Recieved time: Sat Apr 28 19:57:50 2012
  22. 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
  23. 00 3c d4 af 40 00 40 06 74 55 c0 a8 38 01 c0 a8
  24. 38 65 8e 20 26 68 79 e1 63 8c 00 00 00 00 a0 02
  25. 39 08 d4 13 00 00 02 04 05 b4 04 02 08 0a 00 14
  26. b7 23 00 00 00 00 01 03 03 06
  27. id: 4
  28. Packet length: 74
  29. Number of bytes: 74
  30. Recieved time: Sat Apr 28 19:57:50 2012
  31. 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
  32. 00 3c 00 00 40 00 40 06 49 05 c0 a8 38 65 c0 a8
  33. 38 01 26 68 8e 20 b6 c4 e6 e5 79 e1 63 8d a0 12
  34. 38 90 f1 e5 00 00 02 04 05 b4 04 02 08 0a 00 57
  35. a1 2c 00 14 b7 23 01 03 03 05
  36. id: 5
  37. Packet length: 66
  38. Number of bytes: 66
  39. Recieved time: Sat Apr 28 19:57:50 2012
  40. 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
  41. 00 34 d4 b0 40 00 40 06 74 5c c0 a8 38 01 c0 a8
  42. 38 65 8e 20 26 68 79 e1 63 8d b6 c4 e6 e6 80 10
  43. 00 e5 fb c1 00 00 01 01 08 0a 00 14 b7 24 00 57
  44. a1 2c
  45. id: 6
  46. Packet length: 67
  47. Number of bytes: 67
  48. Recieved time: Sat Apr 28 19:57:50 2012
  49. 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
  50. 00 35 d4 b1 40 00 40 06 74 5a c0 a8 38 01 c0 a8
  51. 38 65 8e 20 26 68 79 e1 63 8d b6 c4 e6 e6 80 18
  52. 00 e5 ba b7 00 00 01 01 08 0a 00 14 b7 25 00 57
  53. a1 2c 41
  54. id: 7
  55. Packet length: 66
  56. Number of bytes: 66
  57. Recieved time: Sat Apr 28 19:57:50 2012
  58. 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
  59. 00 34 47 cb 40 00 40 06 01 42 c0 a8 38 65 c0 a8
  60. 38 01 26 68 8e 20 b6 c4 e6 e6 79 e1 63 8e 80 10
  61. 01 c5 f1 dd 00 00 01 01 08 0a 00 57 a1 2e 00 14
  62. b7 25
  63. id: 8
  64. Packet length: 67
  65. Number of bytes: 67
  66. Recieved time: Sat Apr 28 19:57:50 2012
  67. 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
  68. 00 35 47 cc 40 00 40 06 01 40 c0 a8 38 65 c0 a8
  69. 38 01 26 68 8e 20 b6 c4 e6 e6 79 e1 63 8e 80 18
  70. 01 c5 f1 de 00 00 01 01 08 0a 00 57 a1 2e 00 14
  71. b7 25 42
  72. id: 9
  73. Packet length: 66
  74. Number of bytes: 66
  75. Recieved time: Sat Apr 28 19:57:50 2012
  76. 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
  77. 00 34 47 cd 40 00 40 06 01 40 c0 a8 38 65 c0 a8
  78. 38 01 26 68 8e 20 b6 c4 e6 e7 79 e1 63 8e 80 11
  79. 01 c5 f1 dd 00 00 01 01 08 0a 00 57 a1 2e 00 14
  80. b7 25
  81. id: 10
  82. Packet length: 66
  83. Number of bytes: 66
  84. Recieved time: Sat Apr 28 19:57:50 2012
  85. 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
  86. 00 34 d4 b2 40 00 40 06 74 5a c0 a8 38 01 c0 a8
  87. 38 65 8e 20 26 68 79 e1 63 8e b6 c4 e6 e7 80 10
  88. 00 e5 fb bc 00 00 01 01 08 0a 00 14 b7 25 00 57
  89. a1 2e
  90. id: 11
  91. Packet length: 66
  92. Number of bytes: 66
  93. Recieved time: Sat Apr 28 19:57:50 2012
  94. 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
  95. 00 34 d4 b3 40 00 40 06 74 59 c0 a8 38 01 c0 a8
  96. 38 65 8e 20 26 68 79 e1 63 8e b6 c4 e6 e7 80 11
  97. 00 e5 fb bb 00 00 01 01 08 0a 00 14 b7 25 00 57
  98. a1 2e
  99. id: 12
  100. Packet length: 66
  101. Number of bytes: 66
  102. Recieved time: Sat Apr 28 19:57:50 2012
  103. 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
  104. 00 34 47 ce 40 00 40 06 01 3f c0 a8 38 65 c0 a8
  105. 38 01 26 68 8e 20 b6 c4 e6 e8 79 e1 63 8f 80 10
  106. 01 c5 f1 dd 00 00 01 01 08 0a 00 57 a1 2e 00 14
  107. b7 25
  108. id: 13
  109. Packet length: 66
  110. Number of bytes: 66
  111. Recieved time: Sat Apr 28 19:57:50 2012
  112. 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
  113. 00 34 d4 b4 40 00 40 06 74 58 c0 a8 38 01 c0 a8
  114. 38 65 8e 20 26 68 79 e1 63 8f b6 c4 e6 e8 80 10
  115. 00 e5 fb b9 00 00 01 01 08 0a 00 14 b7 26 00 57
  116. a1 2e
hutao@hutao-VirtualBox:~/test3$ sudo ./test
success: device: eth0
id: 1
Packet length: 60
Number of bytes: 60
Recieved time: Sat Apr 28 19:57:50 2012
 ff ff ff ff ff ff 0a 00 27 00 00 00 08 06 00 01
 08 00 06 04 00 01 0a 00 27 00 00 00 c0 a8 38 01
 00 00 00 00 00 00 c0 a8 38 65 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00

id: 2
Packet length: 42
Number of bytes: 42
Recieved time: Sat Apr 28 19:57:50 2012
 0a 00 27 00 00 00 08 00 27 9c ff b1 08 06 00 01
 08 00 06 04 00 02 08 00 27 9c ff b1 c0 a8 38 65
 0a 00 27 00 00 00 c0 a8 38 01

id: 3
Packet length: 74
Number of bytes: 74
Recieved time: Sat Apr 28 19:57:50 2012
 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
 00 3c d4 af 40 00 40 06 74 55 c0 a8 38 01 c0 a8
 38 65 8e 20 26 68 79 e1 63 8c 00 00 00 00 a0 02
 39 08 d4 13 00 00 02 04 05 b4 04 02 08 0a 00 14
 b7 23 00 00 00 00 01 03 03 06

id: 4
Packet length: 74
Number of bytes: 74
Recieved time: Sat Apr 28 19:57:50 2012
 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
 00 3c 00 00 40 00 40 06 49 05 c0 a8 38 65 c0 a8
 38 01 26 68 8e 20 b6 c4 e6 e5 79 e1 63 8d a0 12
 38 90 f1 e5 00 00 02 04 05 b4 04 02 08 0a 00 57
 a1 2c 00 14 b7 23 01 03 03 05

id: 5
Packet length: 66
Number of bytes: 66
Recieved time: Sat Apr 28 19:57:50 2012
 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
 00 34 d4 b0 40 00 40 06 74 5c c0 a8 38 01 c0 a8
 38 65 8e 20 26 68 79 e1 63 8d b6 c4 e6 e6 80 10
 00 e5 fb c1 00 00 01 01 08 0a 00 14 b7 24 00 57
 a1 2c

id: 6
Packet length: 67
Number of bytes: 67
Recieved time: Sat Apr 28 19:57:50 2012
 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
 00 35 d4 b1 40 00 40 06 74 5a c0 a8 38 01 c0 a8
 38 65 8e 20 26 68 79 e1 63 8d b6 c4 e6 e6 80 18
 00 e5 ba b7 00 00 01 01 08 0a 00 14 b7 25 00 57
 a1 2c 41

id: 7
Packet length: 66
Number of bytes: 66
Recieved time: Sat Apr 28 19:57:50 2012
 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
 00 34 47 cb 40 00 40 06 01 42 c0 a8 38 65 c0 a8
 38 01 26 68 8e 20 b6 c4 e6 e6 79 e1 63 8e 80 10
 01 c5 f1 dd 00 00 01 01 08 0a 00 57 a1 2e 00 14
 b7 25

id: 8
Packet length: 67
Number of bytes: 67
Recieved time: Sat Apr 28 19:57:50 2012
 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
 00 35 47 cc 40 00 40 06 01 40 c0 a8 38 65 c0 a8
 38 01 26 68 8e 20 b6 c4 e6 e6 79 e1 63 8e 80 18
 01 c5 f1 de 00 00 01 01 08 0a 00 57 a1 2e 00 14
 b7 25 42

id: 9
Packet length: 66
Number of bytes: 66
Recieved time: Sat Apr 28 19:57:50 2012
 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
 00 34 47 cd 40 00 40 06 01 40 c0 a8 38 65 c0 a8
 38 01 26 68 8e 20 b6 c4 e6 e7 79 e1 63 8e 80 11
 01 c5 f1 dd 00 00 01 01 08 0a 00 57 a1 2e 00 14
 b7 25

id: 10
Packet length: 66
Number of bytes: 66
Recieved time: Sat Apr 28 19:57:50 2012
 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
 00 34 d4 b2 40 00 40 06 74 5a c0 a8 38 01 c0 a8
 38 65 8e 20 26 68 79 e1 63 8e b6 c4 e6 e7 80 10
 00 e5 fb bc 00 00 01 01 08 0a 00 14 b7 25 00 57
 a1 2e

id: 11
Packet length: 66
Number of bytes: 66
Recieved time: Sat Apr 28 19:57:50 2012
 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
 00 34 d4 b3 40 00 40 06 74 59 c0 a8 38 01 c0 a8
 38 65 8e 20 26 68 79 e1 63 8e b6 c4 e6 e7 80 11
 00 e5 fb bb 00 00 01 01 08 0a 00 14 b7 25 00 57
 a1 2e

id: 12
Packet length: 66
Number of bytes: 66
Recieved time: Sat Apr 28 19:57:50 2012
 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
 00 34 47 ce 40 00 40 06 01 3f c0 a8 38 65 c0 a8
 38 01 26 68 8e 20 b6 c4 e6 e8 79 e1 63 8f 80 10
 01 c5 f1 dd 00 00 01 01 08 0a 00 57 a1 2e 00 14
 b7 25

id: 13
Packet length: 66
Number of bytes: 66
Recieved time: Sat Apr 28 19:57:50 2012
 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
 00 34 d4 b4 40 00 40 06 74 58 c0 a8 38 01 c0 a8
 38 65 8e 20 26 68 79 e1 63 8f b6 c4 e6 e8 80 10
 00 e5 fb b9 00 00 01 01 08 0a 00 14 b7 26 00 57
 a1 2e



仔细研究即可发现服务器与客户机是如何通过tcp通信的。









下面的这个程序可以获取eth0的ip和子网掩码等信息:

test5:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pcap.h>
  4. #include <errno.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. int main()
  8. {
  9. /* ask pcap to find a valid device for use to sniff on */
  10. char * dev; /* name of the device */
  11. char errbuf[PCAP_ERRBUF_SIZE];
  12. dev = pcap_lookupdev(errbuf);
  13. /* error checking */
  14. if(!dev)
  15. {
  16. printf("pcap_lookupdev() error: %s\n", errbuf);
  17. exit(1);
  18. }
  19. /* print out device name */
  20. printf("dev name: %s\n", dev);
  21. /* ask pcap for the network address and mask of the device */
  22. bpf_u_int32 netp; /* ip */
  23. bpf_u_int32 maskp; /* subnet mask */
  24. int ret; /* return code */
  25. ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
  26. if(ret == -1)
  27. {
  28. printf("pcap_lookupnet() error: %s\n", errbuf);
  29. exit(1);
  30. }
  31. /* get the network address in a human readable form */
  32. char * net; /* dot notation of the network address */
  33. char * mask; /* dot notation of the network mask */
  34. struct in_addr addr;
  35. addr.s_addr = netp;
  36. net = inet_ntoa(addr);
  37. if(!net)
  38. {
  39. perror("inet_ntoa() ip error: ");
  40. exit(1);
  41. }
  42. printf("ip: %s\n", net);
  43. /* do the same as above for the device's mask */
  44. addr.s_addr = maskp;
  45. mask = inet_ntoa(addr);
  46. if(!mask)
  47. {
  48. perror("inet_ntoa() sub mask error: ");
  49. exit(1);
  50. }
  51. printf("sub mask: %s\n", mask);
  52. return 0;
  53. }
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
  /* ask pcap to find a valid device for use to sniff on */
  char * dev;   /* name of the device */ 
  char errbuf[PCAP_ERRBUF_SIZE];
  dev = pcap_lookupdev(errbuf);

  /* error checking */
  if(!dev)
  {
    printf("pcap_lookupdev() error: %s\n", errbuf);
    exit(1);
  }

  /* print out device name */
  printf("dev name: %s\n", dev);

  /* ask pcap for the network address and mask of the device */
  bpf_u_int32 netp;   /* ip */
  bpf_u_int32 maskp;  /* subnet mask */
  int ret;            /* return code */
  ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);

  if(ret == -1)
  {
    printf("pcap_lookupnet() error: %s\n", errbuf);
    exit(1);
  }

  /* get the network address in a human readable form */
  char * net;   /* dot notation of the network address */
  char * mask;  /* dot notation of the network mask */
  struct in_addr addr;

  addr.s_addr = netp;
  net = inet_ntoa(addr);

  if(!net)
  {
    perror("inet_ntoa() ip error: ");
    exit(1);
  }

  printf("ip: %s\n", net);

  /* do the same as above for the device's mask */
  addr.s_addr = maskp;
  mask = inet_ntoa(addr);
  
  if(!mask)
  {
    perror("inet_ntoa() sub mask error: ");
    exit(1);
  }
  
  printf("sub mask: %s\n", mask);

  return 0;
}


结果如图:





int pcap_lookupnet(const char * device, bpf_u_int32 * netp, bpf_u_int32 * maskp, char * errbuf)
可以获取指定设备的ip地址,子网掩码等信息

netp:传出参数,指定网络接口的ip地址

maskp:传出参数,指定网络接口的子网掩码

pcap_lookupnet()失败返回-1
我们使用inet_ntoa()将其转换为可读的点分十进制形式的字符串






本文的绝大部分来源于libpcap的官方文档:libpcapHakin9LuisMartinGarcia.pdf,可以在官网下载,文档只有9页,不过很详细,还包括了数据链路层,网络层,传输层,应用层等的分析。很好!


更多参考可以man pcap


最后为了方便大家,本文的所有代码和上述的pdf文档都一并上传上来了:

http://download.youkuaiyun.com/detail/htttw/4264686



完成!

【计网 从头自己构建协议】一、libpcap 介绍 & 手撕以太网帧 理论的学习总是枯燥的,想要加深对理论的理解,最好的方法就是自己实践一遍。想要亲手实现各种协议,就必须能够接触底层 API。可惜的是,底层的 API 要么是在驱动里,要么是在系统里,都不对外开放,一般只能接触到运输层的 TCP/UDP。我们必须借助第三方库才能实现对底层操控。libpcap就是这样一个库,它帮我们实现了底层驱动,并将控制权向上开放,提供了发送和监听数据包的功能。著名的网络分析工具 Wireshark 就是基于这个库实现的。 阅读详情

相关推荐

libpcap详解

libpcap(packet capture library),即数据包捕获函数库,是Unix/Linux平台下的网络数据包捕获函数库。它是一个独立于系统的用户层的包捕获API接口,为底层网络监测提供了一个可移植的框架。 一、工作原理 libpcap主要由两部分组成:网络分接头(network tap)和数据过滤器(packet filter)。网络分接头从网络设备驱动程序中收集数据进行拷贝,过滤器决定是否接收该数据包。libpcap利用BSD packet filter(BPF)算法对网卡接收到的链路层数

kking_edc的博客 8806

python代码scapy库 通过 conf 无法获取信息

问题,python代码scapy库 无法通过 conf 获取网卡等信息,也捕获不到数据包。原因是Windows平台需要安装Winpcap才能进行嗅探,安装wireshark亦可

kaihang_cai的博客 8200

libpcap 使用(1)

   计算机网络自顶向下 一书中,介绍了ethereal。 该软件开源,用于抓包分析。版本最新的更名为wireshark,是目前最好的网络抓包分析工具。ethereal主要使用了gtk+ 和 libpcap来进行设计。gtk +提供用户界面,而libpcap是unix/linux平台下的网络数据包捕获函数包,大多数网络监控软件都以它为基础。Libpcap可以在绝大多数类unix平台下工作,提供了网

岳麓听雨专栏 5590

【Scapy】获取流量包【原创】

使用Scapy来嗅探流量包,发送数据包等

一直加班的程序猿 6761

libpcap使用入门实例

libpcap是

tt11212的专栏 903

java libpcap_libpcap详解

libpcap(Packet Capture Library),即数据包捕获函数库,是Unix/Linux平台下的网络数据包捕获函数库。它是一个独立于系统的用户层包捕获的API接口,为底层网络监测提供了一个可移植的框架。一、libpcap工作原理libpcap主要由两部份组成:网络分接头(Network Tap)和数据过滤器(Packet Filter)。网络分接头从网络设备驱动程序中收集数据拷贝...

weixin_33516557的博客 915

libpcap原理及使用

2.9 libpcap 本文最初整理在我的github上SDN-Learning-notes libpcap(Packet Capture Library)即数据包捕获函数库,是Unix/Linux平台下的网络数据包捕获函数库。它是一个独立于系统的用户层包捕获的API接口,为底层网络监测提供了一个可移植的框架。著名的软件TCPDUMP就是在libpcap的的基础上开发而成的libpcap可以实现

虾米的博客 3万+

libpcap

//pcaptest.htypedef struct{//定义以太网的头部数据类型 u_char dmac[6]; u_char smac[6]; u_char etype[2]; }ETHHEADER; typedef struct{//IP 层数据包报文头部的数据类型 u_char version:4; u_char header_len:4; u_char

yuan08shandong的博客 1550

libpcap库的安装与使用

1 安装 sudo apt-get install libpcap-dev 2 使用 需要包含的头文件: #include <pcap.h 编译的时候需要加: -lpcap 利用libpcap函数库开发应用程序的基本步骤: 打开网络设备 设置过滤规则(可选) 捕获数据 关闭网络设备 常用函数: pcap_lookupdev( )(可选) 查看设备名,返回网卡名 pcap_t *pcap_open_live(const char *device,int snaplen,int promisc,

qq_45164331的博客 5262

Linux下使用Qt + libpcap

Libpcap是的英文缩写,即数据包捕获函数库。该库提供的C函数接口用于捕捉经过指定网络接口的数据包,该接口应该是被设为混杂模式。这个在原始套接子中有提到。著名的软件TCPDUMP就是在Libpcap的基础上开发而成的。Libpcap提供的接口函数实现和封装了与数据包截获有关的过程。Libpcap提供了用户级别的网络数据包捕获接口,并充分考虑到应用程序的可移植性。Libpcap可以在绝大多数Linux平台上运行。Wincap。它的工作在上层应用程序与网络接口之间。数据包捕获:捕获流经网卡的原始数据包。

贝勒里恩的博客 2107

避开这些坑!DS18B20温度读取不准、时序混乱的5个常见问题与调试方法

本文深入解析DS18B20温度传感器在应用中常见的5个问题,包括温度读取不准、时序混乱等,并提供详细的调试方法。通过硬件设计优化、精准延时实现和数据解析技巧,帮助开发者有效解决温度值跳变、初始化失败等典型问题,提升OneWire协议下的温度测量精度。

weixin_29185493的博客 463

libpcap的安装

最近参加了一个实训项目,是把一个WireShark抓到的pcapng文件用libpcap库还原成原始的TS流,需求分析弄了一天,安装环境用了一天,接下来再开始写代码,让我们一起完成这个项目吧。 首先是安装CentOS环境(其实只要是Linux就可以),这里给出资源网站:https://www.centos.org/download/ 可以选择DVD download或者最小化安装。 这里注意,如果...

NCU_CirclePlan的博客 2140

Basilisk库教程

要在仿真中执行模块,其调度由Basilisk的[Process]和[Task]容器控制。BSK[Task]包含一系列模块,这些模块都以相同的更新频率执行。一个[Process]本质上是一个任务组,可以包含多个相关的任务。例如,在多星仿真中,你可以为每颗卫星创建一个[Process],以便将相关任务和嵌入式模块有序地组织起来。下图展示了一个示例布局,其中bskSat卫星的动力学被添加到与飞行软件(FSW)算法分开的进程中,这些算法在该卫星上执行。在每个进程中,设置了若干任务,这些任务以指定的频率进行评估。

weixin_57997461的博客 1137

libpcap使用

libpcap使用 libpcap是一个网络数据包捕获函数库,功能非常强大,Linux下著名的tcpdump就是以它为基础的。今天我们利用它来完成一个我们自己的网络嗅探器(sniffer) 首先先介绍一下本次实验的环境: Ubuntu 11.04,IP:192.168.1.1,广播地址:192.168.1.255,子网掩码:255.255.255.0 可以使用下

htttw的专栏 13万+

eNSP搭建基础网络

1、除5的环回地址固定以外,整个其他所有网段基于192.168.1.0/24进行合理的IP地址划分 2、R1-R4每个路由器存在两个环回接口,用于模拟连接pc网段﹔地址也在192.168.1.0/24这个网络范围内 3、R1-R4上不能直接编写到达5.5.5.0/24的静态路由,但依然可以访问 4、全网可达,尽量减少每台路由器,路由表条目数量,避免环路出现5R4与R5间,正常100oA链路通信,故障时自动改为100M 全网使用192.168.1.0/24网段进行划分,尽量减少路由条目Pc端IP使用pHcP技

在月光下棕榈树的叶子在瑟瑟抖动 8469

【AI应用实战-WorkBuddy】WorkBuddy 能帮你做什么(一)

文章摘要: WorkBuddy是一款AI工作助手,专为提升效率而设计,适用于经常处理文档、代码、数据分析等重复性任务的职场人士。它能通过自然语言交互快速完成五大核心场景任务: 周报撰写:输入工作要点,10分钟生成专业周报; 代码调试:解析报错信息,3分钟提供解决方案; Excel分析:自动计算数据趋势并生成图表和结论; 自动化脚本:将重复流程转为脚本,节省98%时间; 文档生成:根据代码自动补充README、API文档和注释。 效果对比:传统手动操作耗时1-3小时的任务,WorkBuddy可将时间缩短至10

349

python调用libpcap_python-libpcap

python-libpcapCython libpcap, read/write/merge/captureFeaturesRead pcap fileWrite pcap fileMerge pcap fileMulti-file quick mergeGet first ifaceGet iface listSend raw packetCapture dataInstallationTo i...

weixin_33139275的博客 1245

JavaFx 教程

JavaFx 教程

2012年开始工作,全栈开发老兵,目前已是一个老师,分享这么多年的心得体会 784

【笔记】libpcap安装与使用

自用

shandianchengzi的博客 1万+

11.Labview实现用户界面切换的几种方式---通过VI间相互调用

本文介绍了界面切换的几种方式,分别是重入和引用①重入方式可以通过调用子VI的方式打开被调用的界面,往往应用于弹窗等的设置程序。②引用方式分两种,一种是打开引用,一种是静态引用。区别在于打开引用需要设置被打开VI的目标地址,静态引用仅需在引用时绑定VI的位置即可。③推荐使用静态引用的方式切换界面。④使用引用打开界面时,需通过属性节点和调用节点来设置程序的状态。更多内容欢迎大家补充和留言讨论~本文介绍了GUI界面设计相关的程序,更多相关文章后续持续更新,请关注作者不迷路~本期就到这里,再见~

关注我,更多技术问题欢迎私聊~ 9545

深入YOLOv8内部核心:用RepNCSPELAN4深度重构主干网络,即插即用的高效涨点方案

本文提出了一种改进YOLOv8目标检测模型的方法,通过在YOLOv8中引入RepNCSPELAN模块来提高检测性能。该模块融合了RepVGG重参数化思想与CSP-ELAN结构,在保持推理速度的同时增强特征表达能力。实验结果表明,改进后的RepNCSPELAN-YOLOv8相比原模型在多项指标上均有提升:准确率从0.84提高到0.86,召回率从0.72提升至0.81,mAP50和mAP50-95也分别提高了0.06和0.04。文章详细介绍了模块设计原理和移植步骤,包括配置文件创建、代码修改等关键环节,为YOL

FJN110的博客 186

Libpcap使用总结

<br /><br />                                      <br /><br />Libpcap使用总结<br /><br />libpcap是一个与实现无关的访问操作系统所提供的分组捕获机制的分组捕获函数库,用于访问数据链路层。这个库为不同的平台提供了一致的编程接口,在安装了 libpcap 的平台上,以 libpcap 为接口写的程序、应用,能够自由的跨平台使用。操作系统所提供的分组捕获机制主要有三种:BPF(Berkeley Packet Filter),DL

qiaoxx094的专栏 884

一个服务如何被找到、被调用、被看见:注册中心、发布注册、发现调用与服务监控的治理闭环

服务数量一多,“对方在哪儿”就成了时刻变化的变量。本文沿发布、注册、发现、调用、监控的治理闭环展开:注册中心的数据模型、健康检查与AP/CP取舍,自我保护、推空保护与本地快照三道自保机制;服务发布的启动器、动态代理、发布管理器、协议服务器与登记顺序;消费端的服务目录、请求ID配对、六种集群容错与三种发现模式;日志、指标、链路三支柱与熔断舱壁。配套五个Java演示程序实测:默认参数下宕机实例平均240秒才被摘除,优雅下线可降至45秒,统计窗口长于租约会让自我保护失效,尾部采样可捕获全部慢请求。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 169万+

libpcap使用整理

Libpcap是Packet Capture Libray的英文缩写,即数据包捕获函数库。该库提供的C函数接口用于捕捉经过指定网络接口的数据包,该接口应该是被设为混杂模式。这个在原始套接字中有提到。

qq_32038155的博客 3943

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

[笔记] libpcap编译及使用

官网以上就是今天要讲的内容,本文仅仅简单介绍了libpcap安装和使用。libpcap库使用关于博主码云:https://gitee.com/shiver个人博客:www.shiver.fun。

二次元怪兽的博客 1958

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Libpcap一 libpcap简介与编译

a

yuanbinquan的专栏 2338

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

上一篇: Libpcap开发集介绍
下一篇: Qt Creator的配置和开发初步测试
Scutware
博客等级 码龄14年 4粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值