【问题标题】:Python-based Socket program accept by libPcap(C-based)基于 Python 的 Socket 程序接受 libPcap(C-based)
【发布时间】:2013-02-02 14:29:09
【问题描述】:

亲爱的:

我使用基于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 来捕获字符串数据。

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

谁能给我一些建议来解决这个问题?

非常感谢您的帮助。

【问题讨论】:

  • 每次运行客户端时,它都会重新连接到服务器。您的服务器尚未准备好进行多个连接(我认为)。
  • 我假设 python 部分中的无限打印循环是复制粘贴错误,而不是真的存在?
  • 请记住,必须有一个实际的服务器在服务器端运行——我认为libpcap 不会捕获任何进入 NIC 的数据,即使它没有传递到开放端口。 (除非使用混杂模式或原始套接字,或者这两者是相关的。)如果您的服务器(您没有包括在内)被编码为只接受一个连接然后退出,这将解释这种行为。
  • 亲爱的 amaurea:是的,这是复制粘贴错误。
  • 亲爱的millimoose:但我认为libpacp 具有混杂模式的能力,因为它是由AF_PACKET 实现的。而且我第一次确实捕获了字符串数据,但是第二次捕获了套接字错误。不想在服务端使用socket绑定怎么办?

标签: python linux sockets networking pcap


【解决方案1】:

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

如果您有一个进程在某台机器上运行,使用 libpcap 监听数据包,那么不会在该机器上创建一个套接字来接收发送到某个特定 TCP 的数据包或 UDP 端口。

当您的程序第一次尝试将数据包发送到有问题的 UDP 端口时,您发送它的机器可能会看到它被发送到没有套接字正在侦听的 UDP 端口,并发送回一个ICMP 端口不可达消息。发送调用已经完成; UDP 是一种无连接协议,没有可靠的传递保证,因此 UDP 发送确实不等待任何类型的回复 - 如果数据包发送到线路上,这被认为是“成功”,因为没有可以在 UDP 级别进行其他成功交付检查。

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

所以这就是您在使用 libpcap 的嗅探器(不是服务器!)应用程序中看到第一个数据包而不是第二个数据包的原因。

所以当他/她说“必须有一个实际的服务器在服务器端运行”时,它是 100% 正确的。编写一个 - 使用常规套接字,而不是 libpcap 和它可能使用的任何机制(Linux 上的 AF_PACKET 套接字,*BSD 和 OS X 上的 BPF 设备等),然后在服务器机器上运行它。您可以也运行基于 libpcap 的 sniffer 程序,或其他一些嗅探器程序,例如 tcpdump 或 {Wireshark, TShark},以查看发生了什么电线。

【讨论】:

  • 感谢您的回复。我知道我的问题。但是我想问是否可以发送我不需要在服务器端绑定IP地址的字符串数据?因为我需要做数据包重定向,服务器端会得到不属于它的数据包(这意味着数据包字段与服务器端不匹配,例如IP地址,MAC地址)。谢谢。
  • ICMP Port Unreachable 消息将由服务器发送,除非服务器上正在运行绑定到相关 UDP 端口号的进程。如果您无法运行这样的服务器,您将不得不让客户端程序以某种方式对这些消息没有问题 - 例如,not 连接客户端中的套接字,并使用 Python 等价物sendto(),不管是什么,可能这样做。
  • 亲爱的小伙子:谢谢你的回复,你的建议真的很管用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-09
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多