python构造icmp数据包_构造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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值