I'm creating a networking protocol in application space on top of UDP in python for homework. I need to represent the source port and destination port as 16-bit numbers. All attempts have failed.
The way I'm testing this is by creating a udp socket and looking at the return value of sendto()
. Here's your typical socket code:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
addr = ("127.0.0.1", 1234)
Ports range from 0 to 65535. Let's say I choose a port of 65000. I want sendto()
to return 2
(2 bytes = 16 bits sent). Here's what I've tried:
I call the following and get:
>>>mySock.sendto(655000, addr)
TypeError: must be string or buffer, not int
Ok, let's try using bytes()
>>>mySock.sendto(bytes(65000), addr)
5
Hm, that's not what I want. That is making each number into a character that is a single byte.
What if I bitwise or it with 0x0000?
>>>mySock.sendto(bytes(65000 | 0x0000), addr)
5
Well, darn it! The closest thing I've come to is messing around with hex()
and bytearray()
. See below.
>>>hex(65000)
'0xfde8'
>>>mySock.sendto('\xfde8', addr)
3
Shouldn't that say 2 bytes? I'm not sure how this works. Also, when the number is less than 16384 I want to preserve the preceding 0's. So, for example, if the port number is 255 (0b0000000011111111) I want it to remain as a 2 byte data structure (0x00FF) rather than truncating down to 0xFF or 0b11111111.
If you want to send binary data, please use module struct
. That will help you to encode the string and to make sure that you are using the proper endianness. For example:
>>> import struct
>>> struct.pack('!H', 65000)
'\xfd\xe8'
That's 65000 as an unsigned short, in network order (big endian)