构造icmp包python-socket-收包解包

socket收包,如前面的文章实现了python socket发ping包,并且收到了对端的返回结果,那么如何把返回的包也用socket收上来呢?疑问,socket建立了一个管道,管道建好以后可以通过管道把包发出去,怎么保证收到的包也可以从管道上来呢?答案:socket只要建立好之后,就有发包和收包两种方法。直接使用 socket.recv方法就可以。但是 recv方法一次只能收一个包,和sendto方法一次只能发送一个包的道理类似。收上来的包如果不做类型转化默认为 str类型,需要转化为bytearray类型,才能通过ICMP协议规定的组织结构,通过字节偏移取出各个字段。

另外:如果要写连续ping 多个不同的ip地址,并且收包完成的话,需要设计总的超时时间。这个在下一节中在实现。

recv,解包代码如下:

源码如下:


#!/bin/env/python

import socket

import struct

import os

import time

_ICMP_HDR_OFFSET =20

_ICMP_ECHO_REPLY =0

_ICMP_ID_OFFSET = _ICMP_HDR_OFFSET +4

_ICMP_IDENT_OFFSET = _ICMP_HDR_OFFSET +6

_ICMP_PAYLOAD_OFFSET = _ICMP_HDR_OFFSET +8

# create icmp socket

def create_socket():

proto ='ICMP'

    try:

icmp_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)

print icmp_socket

except Exception as e:

raise e

return icmp_socket

def checksum(source_string):

"""

I'm not too confident that this is right but testing seems

to suggest that it gives the same answers as in_cksum in ping.c

"""

    sum =0

    countTo = (len(source_string)/2)*2

    count =0

    while count

thisVal =ord(source_string[count +1])*256 +ord(source_string[count])

sum = sum + thisVal

sum = sum &0xffffffff # Necessary?

        count = count +2

    if countTo

sum = sum +ord(source_string[len(source_string) -1])

sum = sum &0xffffffff # Necessary?

    sum = (sum >>16)  +  (sum &0xffff)

sum = sum + (sum >>16)

answer = ~sum

answer = answer &0xffff

    # Swap bytes. Bugger me if I know why.

    answer = answer >>8 | (answer <<8 &0xff00)

return answer

# generate icmp data

def generate_pkg():

## ICMP pkg header

  pkt_id = os.getpid()

ident =0

  pkg_header_pre = struct.pack("!BBHHH",8,0,0, pkt_id, ident)

payload = struct.pack("d", time.time())

pkgheader_check = checksum(pkg_header_pre+payload)

pkg_header = struct.pack("!BBHHH",8,0, pkgheader_check, pkt_id, ident)

pkg = pkg_header+payload

return pkg

def send_pkg(icmp_socket,pkt,dst_addr):

icmp_socket.sendto(pkt,dst_addr)

def recrive_pkg(icmp_socket):

pkts = []

icmp_socket.settimeout(100)

p = icmp_socket.recv(64)

print type(p)

pkt =bytearray(p)

print type(pkt)

pkts.append((bytearray(pkt), time.time()))

print pkts

print pkt[_ICMP_HDR_OFFSET]

pkt_id = (pkt[_ICMP_ID_OFFSET] <<8) + pkt[_ICMP_ID_OFFSET +1]

pkt_ident = (pkt[_ICMP_IDENT_OFFSET] <<8) + pkt[_ICMP_IDENT_OFFSET +1]

payload = pkt[_ICMP_PAYLOAD_OFFSET :]

print pkt_id

print pkt_ident

print payload

if __name__ =='__main__':

icmp_socket = create_socket()

pkt = generate_pkg()

dst_addr ='61.135.169.121'

    real_dst_addr = (dst_addr,0)

send_pkg(icmp_socket, pkt, real_dst_addr)

recrive_pkg(icmp_socket)

你可能感兴趣的:(构造icmp包python-socket-收包解包)