基于Python的Socket程序由libPcap接受(基于C语言)

时间:2013-02-02 14:29:09

标签: python linux sockets networking pcap

亲爱的:

我使用基于python的套接字客户端来发送字符串数据(即日志数据)。

另一方面,我使用 libpcap来嗅探服务器端的字符串数据

但是当我第二次向服务器端发送字符串数据时,我在客户端出现了错误。

如下错误:

Traceback (most recent call last):
  File "./udp_client_not_sendback.py", line 21, in <module>
    s.sendall(data) #Send UDP data
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 111] Connection refused

以下是客户端和服务器端的代码:

客户端(Python)

import socket, sys

host = sys.argv[1] #Server IP Address

textport = sys.argv[2] #Server Binding Port

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #socket

try:
    port = int(textport)
except ValueError:
    port = socket.getservbyname(textport, 'udp')

s.connect((host, port)) #connect

while(1):
    print "Enter data to transmit:"

    data = sys.stdin.readline().strip() #UDP data

    s.sendall(data) #Send UDP data

服务器端(C libpcap)

    pcap_handler_func(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
    {
    char timebuf[64];
    char addrstr[64];
    struct ether_header *ethhdr = (struct ether_header *)bytes;
    struct iphdr *ipv4h;
    struct ip6_hdr *ipv6h;

    memset(timebuf, 0, sizeof(timebuf));
    if (ctime_r(&h->ts.tv_sec, timebuf) == NULL) {
    return;
    }
    timebuf[strlen(timebuf) - 1] = '\0';
    printf("%s, caplen:%d, len:%d, ", timebuf, h->caplen, h->len);
    ipv4h = (struct iphdr *)(bytes + sizeof(struct ether_header));
    inet_ntop(AF_INET, &ipv4h->saddr, addrstr, sizeof(addrstr));
    printf("src[%s]\n", addrstr);

    return;
    }

    int main()
    {
    pcap_t *p;
    char errbuf[PCAP_ERRBUF_SIZE];
    char cmdstr[] = "udp";
    struct bpf_program bpfprog;

    p = pcap_open_live("eth1", 65536, 1, 10, errbuf);

    //Filter
    if (pcap_setfilter(p, &bpfprog) < 0) {
    fprintf(stderr, "%s\n", pcap_geterr(p));
    return 1;
    }

    //Packet action
    if (pcap_loop(p, -1, pcap_handler_func, NULL) < 0) {
    fprintf(stderr, "%s\n", pcap_geterr(p));
    pcap_close(p);
    return 1;
    }

    pcap_close(p);
    return 0;
    }

我认为问题是我没有绑定服务器端的套接字,我只是使用pcap来捕获字符串数据。

所以在第二次它发生了客户端的套接字错误。

任何人都可以给我一些建议来克服这个问题吗?

非常感谢你的帮助。

1 个答案:

答案 0 :(得分:0)

libpcap及其使用的捕获机制是 NOT ,旨在用于编写TCP / UDP / IP服务器时!它们旨在1)允许被动捕获数据包和(在某些情况下和更新版本的libpcap)数据包注入和2)在链路层上运行并且没有实现的协议的用户模式实现在OS内核中。

如果某个计算机上正在运行进程,使用libpcap侦听数据包, NOT 会在该计算机上创建一个套接字,以接收发送到某个特定TCP的数据包或UDP端口。

当您的程序第一次尝试将数据包发送到相关的UDP端口时,您发送它的计算机可能会发现它正被发送到没有套接字正在侦听的UDP端口,并发回一个ICMP Port Unreachable消息。发送呼叫已经完成; UDP是一种无连接协议,没有可靠的传送保证,所以UDP发送 NOT 等待任何类型的回复 - 如果数据包发送到线路上,那被认为是“成功”,因为没有可以在UDP级别进行其他成功交付检查。

但是,当您在客户端程序中连接套接字时,客户端计算机的ICMP实现(如果它看到ICMP Port Unreachable消息)将在套接字上设置一个指示器,告诉程序 previous 无法传递UDP数据包(因为没有任何东西可以传递它)。在该套接字上的接收尝试 - 或者,看起来,后续尝试在该套接字上发送数据包 - 将返回“连接被拒绝”错误,表明先前发送的数据包无法交付。这也意味着发送数据包的第二次尝试实际上不会发送数据包;您必须进行另一次尝试,我认为这将成功发送数据包,但如果没有程序侦听服务器上的UDP端口,它将再次获得ICMP端口无法访问。

所以那是为什么你在使用libpcap的嗅探器( NOT 服务器!)应用程序中看到第一个数据包而不是第二个数据包。

当他/她说“必须在服务器端运行实际服务器”时,毫无疑问是100%正确的。写一个 - 使用常规套接字,而不是libpcap及其可能使用的任何机制(Linux上的AF_PACKET套接字,* BSD和OS X上的BPF设备等),并在服务器计算机上运行它。您也可以同时运行基于libpcap的嗅探器程序,或同时运行其他一些嗅探器程序,如tcpdump或{Wireshark,TShark},以查看正在发生的事情。丝。