• 用python来调试网络程序


    需要联调的程序,沟通联调起来总是各种麻烦,如果自己能写个简单一点的“测试机”,事情就很easy了;或者有时候想做“中间人”,看看网路上到底传些什么。前面写了串口的测试机,今天尝试了一下UDP的。

    import socket
    from struct import *
    
    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
    
    while True:
        packet = s.recvfrom(65565)
        packet = packet[0]
    
        ip_header = packet[0:20]
        iph = unpack('!BBHHHBBH4s4s', ip_header)
    
        version_ihl = iph[0]
        version = version_ihl >> 4
        ihl = version_ihl & 0xf
    
        ttl = iph[5]
        protocol = iph[6]
        s_addr = socket.inet_ntoa(iph[8])
        d_addr = socket.inet_ntoa(iph[9])
    
        print '---> src_addr:'+s_addr+',dst_addr:'+d_addr
    
        udp_header = packet[20:28]
        udph = unpack('!HHHH', udp_header)
    
        s_port = udph[0]
        d_port = udph[1]
        data_length = udph[3]
    
        print '    src_port:'+str(s_port)+',dst_port:'+str(d_port)

    简单做一下注释:

    1. raw_socket,字面理解是“裸”套接字,这个“裸”对应用编程人员来说就是,未经过解析的。

    2. recvfrom(length),注意,这里的参数是缓存区的大小,并不是port。因为我们在这里recvfrom()到的,是本机所有的UDP datagram(tcp使用IPPROTO_TCP,ICMP使用IPPROTO_ICMP)。

    3. recvfrom的返回是一个tuple,类似下面:

    ("E x00xxccxfcx00x000x06j%J}Gx13xc0xa8x01x06x01xbbxa3xdcx0bxbeIxbfx1aF[x83Px18xffxffx88xf6x00x00x17x03x01x00x1cxbbTxb3x07}xb0xedqEx1exe7;-x03x9bUxb7xb1rxd2x9e]xa1xb8xacxa4Vx9ax17x03x01x00*xedx1fxdaxa4##Qex9axe9xd6xadNxf4x9bxc4xf0C'x01xc4x82xdbxb2x8d(xa5xd0x06x95x13WOx0fx8ex1cxa6fx1dxdfxe1x", ('74.125.71.19', 0))

    4. unpack是struct包中的函数,format字符串的含义在这里有解释。如:‘!’表示big-endian,也可以使用‘>’代替;‘H’表示unsigned short。

    另一个,截取TCP包的代码,IP头部分与上面udp解析一样:

        tcp_header = packet[20:40]
    
        #now unpack them :)
        tcph = unpack('!HHLLBBHHH' , tcp_header)
    
        source_port = tcph[0]
        dest_port = tcph[1]
        sequence = tcph[2]
        acknowledgement = tcph[3]
        doff_reserved = tcph[4]
        tcph_length = doff_reserved >> 4
    
        print 'Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Sequence Number : ' + str(sequence) + ' Acknowledgement : ' + str(acknowledgement) + ' TCP header length : ' + str(tcph_length)
    
        h_size = ihl * 4 + tcph_length * 4
        data_size = len(packet) - h_size
    
        #get data from the packet
        data = packet[data_size:]
    
        print 'Data : ' + data

    另外,此方法还支持PF_PACKET,所以可以直接用来抓取以太网数据(只有x-nix系统支持PF_PACKET,所以,windows系统还得使用wpcap)。

    想要抓取经过自己网卡的所有数据包,需要网卡进入“promiscuous mode”。有两种方法:手动“ifconfig eth0 promisc”打开;使用ioctl,修改socket的配置"ifr.ifr_flags |= IFF_PROMISC"。

    data.encode("hex")
  • 相关阅读:
    unity remote 连接设置
    cocos2d-x android环境中lua脚本的io操作
    记一次图片存储方式的修改(使用wcf和iis进行图片的上传和发布)
    是时候写点什么了
    VS2012+EF6+Mysql配置心路历程
    MVC中调用Public_Class时,VS2012老提示:当前上下文中不存在名称“Json”的解决方法
    DWZ错误的解决:0x800a13af
    MVC与DWZ整合中部分问题的解决
    MVC+EF6使用MySQL+CodeFirst的详细配置
    XHEditor(MVC4+DWZ) 部分问题的解决
  • 原文地址:https://www.cnblogs.com/pied/p/4315406.html
Copyright © 2020-2023  润新知