J’ai utilisé TCP pour envoyer des données au serveur Python. Les données sont comme:
struct protocol { unsigned char prot; int id; char name[32]; }
Regardez le champ du name
, il s’agit d’une chaîne dont la taille est terminée par un caractère NULL et dont la taille maximale est 32. Maintenant, j’utilise strcpy
.
protocol p; memset(&p, 0, sizeof(p)); strcpy(name, "abc");
Maintenant, je le décompresse en python.
prot,id,name = struct.unpack("@Bi32s")
Maintenant, le len(name)
est 32. Mais il me faut la chaîne "abc"
lorsque la longueur est 3.
Comment puis je faire ça?
Après le déballage, vous pouvez simplement faire un:
name = name.split('\0', 1)[0]
Sinon, vous pouvez utiliser le module ctypes
:
name = ctypes.create_ssortingng_buffer(name).value
Il suffit d’obtenir la sous-chaîne jusqu’au premier \0
:
prot,id,name = struct.unpack("@Bi32s") name= name[:name.index("\0")]
Cela a la particularité de vérifier et d’échouer ( ValueError
) si \0
n’apparaît pas dans la chaîne.
Partitionnez-le avec un caractère nul ( '\0'
) après le décompactage:
>>> prot, id, name = struct.unpack('@Bi32s', b'\0\0\0\0\0\0\0\0abc' + b'\0' * 29) >>> name, _, _ = name.partition('\0') >>> name 'abc'
Alternative utilisant des ctypes
:
>>> from ctypes import * >>> >>> class Protocol(Structure): ... _fields_ = [("prot", c_char), ... ("id", c_int), ... ('name', c_char * 32)] ... >>> # sock.recv_into(buf) in real program ... buf = create_ssortingng_buffer(b'\0\0\0\0\0\0\0\0abc' + b'\0' * 29) >>> p = cast(buf, POINTER(Protocol)) >>> p[0].name 'abc'
Pourquoi ne pas utiliser rssortingp pour enlever le rembourrage?
prot,id,name = struct.unpack("@Bi32s") name = name.rssortingp(b'\0')
Cela vous permettra également d’utiliser les 32 octets pour stocker le nom sans terminateur zéro. Cependant, cela implique que TOUS les octets de remplissage soient définis sur zéro.