这里主要通过以2015年做过的一个项目:深交所行情的二进制数据接收以及分析为例来介绍python struct模块和socket模块的使用。
先上最后一位验证码的计算方法:
def checksum(pack_content):
"""
pack_content为本次要发送的二进制内容
""" cks = 0 for i in pack_content: a = struct.unpack('!B',i) cks += a[0] return cks%256
一、Struct模块
前面已讲过,了解python模块有两大神技:help与dir方法,通过help可以查看大概定义以及用法, 通过dir可以了解属性以及方法。
首先使用help方法了解定义及其大致用法:help(struct)
DESCRIPTION Functions to convert between Python values and C structs represented as Python strings. It uses format strings (explained below) as compact descriptions of the lay-out of the C structs and the intended conversion to/from Python values. The optional first format char indicates byte order, size and alignment: @: native order, size & alignment (default) =: native order, std. size & alignment <: little-endian, std. size & alignment >: big-endian, std. size & alignment !: same as > The remaining chars indicate types of args and must match exactly; these can be preceded by a decimal repeat count: x: pad byte (no data); c:char; b:signed byte; B:unsigned byte; ?: _Bool (requires C99; if not available, char is used instead) h:short; H:unsigned short; i:int; I:unsigned int; l:long; L:unsigned long; f:float; d:double. Special cases (preceding decimal count indicates length): s:string (array of char); p: pascal string (with count byte). Special case (only available in native format): P:an integer type that is wide enough to hold a pointer. Special case (not in native mode unless 'long long' in platform C): q:long long; Q:unsigned long long Whitespace between formats is ignored. The variable struct.error is an exception raised on errors.
解释:用来做python数据与C 结构代表的python字符(一般为通过python socket模块接收二进制数据流后的字符形式)数据之间转换的函数集。它用指定格式的字符串来描述二进制数据流,并且通过这种指定格式的字符串来实现python数据与二进制数据流二者之间的转换, 字节流的顺序以及格式由这种指定格式字符串的第一个字符决定。
举例:
这里以一段二进制行情包的数据为例
import struct raw_str = '\x00\x01\x8c\xe1\x00\x00\x00_16025380010000023102 \x00\x0101\x00G\x8e:x\xc1*\xbe S1000001070030468786 0 12\x00\x00\x00\x00\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x00>\x80253800\x00\x00\x00\xe2' format_string = '!II3s6s8s4sH2sq8s10s12s4s4s1s1sqq6s' struct.unpack_from(format_string, raw_str, 0)
结果为:(101601, 95, '160', '253800', '10000023', '102 ', 1, '01', 20141105131629246L, ' ', 'S100000107', '0030468786 ', '0 ',', '1', '2', 200, 16000, '253800')
pack_con = (101601, 95, '160', '253800', '10000023', '102 ', 1, '01', 20141105131629246L, ' ', 'S100000107', '0030468786 ', '0 ',', '1', '2', 200, 16000, '253800')
buffer_size = struct.calcsize(format_string)
msg_pack = create_string_buffer(buffer_size) struct.pack_into(fomat_string, msg_pack, 0, *pack_con)print msg_pack.raw
结果为:'\x00\x01\x8c\xe1\x00\x00\x00_16025380010000023102 \x00\x0101\x00G\x8e:x\xc1*\xbe S1000001070030468786 0 12\x00\x00\
x00\x00\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x00>\x80253800'
从上面例子可以出通过struct可以实现C 结构代表的python字符与python数据之间的转换。
通过上面的例子, 首先最需先了解format_string的相关的语法与写法, 先看两张图:
左图是各个format char所代表的数据类型以及字节长度,右图是讲解第一个format char所代表的的含义(即接收字节流的顺序以及格式)。
二、socket
关于socket的介绍,网上有很多, 这里只简单的说下。
socket的本质是编程接口, 是双向通信连接以及数据交换的一端。连接方式有udp和tcp 两种。
创建socket端的代码很简单:
import socket
HOST = socket.gethostbyname(socket.gethostname()) sck = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sck.bind((HOST,PORT)) sck.listen(0)
while 1:
conn, addr = sck.accept()
binary_content = conn.recv(8)
这里接收的binary_content 就可以直接作为上述例子中raw_str变量通过struct模块进行编译了。
注:这里的接收字节的长度一般看一段报文头中的某个字段值(深交所报文的前八个字节为头部), 具体可以查看提供规则方的官方接口文档。
Copyright © 2021.aoyanming个人博客站
发表评论