2009-03-26 16 views
9

Digamos que tengo una conexión de socket, y el oyente de terceros en el otro lado espera que los datos fluyan de una manera muy estructurada. Por ejemplo, busca un byte sin signo que denota un tipo de mensaje que se envía, seguido de un entero sin signo que denota la longitud del mensaje, luego otro byte sin signo que es realmente un campo de bit con algunas banderas configuradas o desarmadas y etc.Escribir datos binarios en un socket (o archivo) con Python

¿Cómo haré esto en python? Me pregunto cómo generar estos datos de manera confiable y asegurarme de que los estoy enviando correctamente (es decir, que realmente estoy enviando un byte sin signo en lugar de decir un entero con signo o, lo que es peor, una cadena).

Respuesta

11

Utilice el módulo struct para construir un búfer y escribir eso.

0

En el nivel más bajo, la E/S de socket consiste en leer o escribir una cadena de valores de bytes en un socket. Para hacer esto, codifico la información para que se escriba como una cadena de caracteres que contiene los valores de byte, y la escribo en el socket. Lo hago creando una supercuerda y luego añadiendo un carácter a la vez. por ejemplo, para crear un Modbus/Ethernet petición de lectura:

readRequest = """""" 
    readRequest += chr(self.transactionID/0x100) # Transaction ID MSB   (0) 
    readRequest += chr(self.transactionID % 0x100) # Transaction ID LSB   (1) 
    readRequest += chr(0)       # Protocol ID MSB (Always 0) (2) 
    readRequest += chr(0)       # Protocol ID LSB (Always 0) (3) 
    readRequest += chr(0)       # Length MSB (Always 0)  (4) 
    readRequest += chr(6)       # Length LSB (Always 6)  (5) 
    readRequest += chr(0)       # Unit ID (Always 0)   (6) 

    readRequest += chr(0x04)      # Function code 4  (0) 
    readRequest += chr(startOffset/0x100)   # Starting offset MSB (1) 
    readRequest += chr(startOffset % 0x100)   # Starting offset LSB (2) 
    readRequest += chr(0)       # Word count MSB  (3) 
    readRequest += chr(2 * nToRead)     # Word count LSB  (4) 

    sockOutfile.write(readRequest) 

para convertir los valores de varios bytes en cadenas de caracteres para que puedan ser añadidos a la cadena de E/S, utilice la función en el módulo struct 'Pack()' . Esta función convierte uno o más valores de bytes individuales o múltiples en una cadena de valores de bytes individuales.

Por supuesto, este método es tan simple como un martillo. Deberá corregirse cuando la codificación de caracteres predeterminada en una cadena sea Unicode en lugar de ASCII.

+0

Esto no es una buena idea. Es propenso a errores y difícil de mantener. El módulo struct es una forma mucho mejor de hacer esto. – Ferruccio

+0

Sí, tengo que estar de acuerdo. Desafortunadamente, escribí esto mientras aprendía Python, y lo escribí como si todavía estuviera escribiendo en C. – mkClark

4

Una forma muy elegante de manejar estas transiciones entre objetos de Python y una representación binaria (ambas direcciones) está utilizando el Construct library.

En su documentación encontrará muchos buenos ejemplos de cómo usarlo. Lo he usado yo mismo desde hace varios años para protocolos de comunicaciones en serie y descodificación de datos binarios.

Cuestiones relacionadas