0

亲爱的大家:

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

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

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

非常感谢您的帮助。

4

1 回答 1

0

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

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

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

However, as you connected the socket in the client program, the client machine's ICMP implementation, if it sees the ICMP Port Unreachable message, will set an indicator on the socket to tell the program that the previous UDP packet couldn't be delivered (as there was nothing to which to deliver it). A receive attempt on that socket - or, it appears, a subsequent attempt to send a packet on that socket - will return the "connection refused" error as an indication that the previously-sent packet couldn't be delivered. It will also mean that the second attempt to send the packet won't actually send the packet; you'd have to make another尝试,我认为,这将成功发送数据包,尽管如果服务器上没有程序监听该 UDP 端口,它将再次获得 ICMP 端口不可达。

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

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

于 2013-02-02T22:13:41.047 回答