A gotcha with Python's socket.htonl() and ntohl()
Here is something that I ran into the other day:
the socket module's
htonl() and ntohl() functions will return signed numbers under
some circumstances, not unsigned ones, which means that for some input
values they will return negative numbers.
(Some quick testing suggests that this happens on 32-bit x86 machines
but not 64-bit x86 Linux machines; all of the 32-bit machines I have
access to are running some version of Python 2.5. A quick test to see if
this is happening to you is checking what socket.htonl(255) returns.)
This is kind of annoying. The underlying C API is specifically
documented as returning unsigned numbers and in many circumstances you
really need them even in Python, which means that you need to force
the results into unsigned yourself.
(This is probably an actual Python bug that thus might get fixed
sometime.)
PS: to fix this problem, just mask the results with 0xffffffffL:
M32 = 0xffffffffL
def htonl(n):
return socket.htonl(n) & M32
def ntohl(n):
return socket.ntohl(n) & M32
As a side effect, this explicitly forces the results to be Python longs
instead of integers. This generally doesn't matter (although I know of
one case where it does or did), and besides you don't
really have a choice; if you want to represent arbitrary IPv4 addresses
as unsigned integers on 32-bit Python machines, you have no choice but
to use Python longs.