You almost certainly don't need to call htons and then copy the 2 bytes into a buffer—see Keith's answer for why.
However, if you do need to do this (maybe you're crafting IP packets to compare to captured wire packets as a test or something?), you can.
First, if you're using a bytearray (or anything else that meets the writable buffer protocol), you just use normal list-style slice assignment:
# like C's memcpy(buf+i, foo, 2)
buf[i:i+2] = foo
You don't have that two-byte string foo; you have a short integer. In C, you can turn that into a pointer to two bytes just by using the & operator to get its address, but Python can't do that. Fortunately, there's a standard library module called struct designed for exactly this kind of thing:
t = socket.htons(int(port))
buf[i:i+2] = struct.pack('h', t)
Or, because struct can handle endianness for you:
t = int(port)
buf[i:i+2] = struct.pack('!h', t)
However, often you don't even need the buffer copying; you can define the entire structure all at once inside struct. For example, if you're trying to pack an IP address and port into a 6-byte array, you could do this:
buf = bytearray(6)
i = 0
addrbytes = [int(part) for part in addr.split('.')]
buf[i:i+4] = struct.pack('4B', addrbytes[0], addrbytes[1], addrbytes[2], addrbytes[3])
i += 4
portshort = int(port)
buf[i:i+2] = struct.pack('!h', portshort)
But this is much simpler:
addrbytes = [int(part) for part in addr.split('.')]
portshort = int(port)
buf = struct.pack('!4Bh', addrbytes[0], addrbytes[1], addrbytes[2], addrbytes[3], portshort)
I've just defined a structure that's in network order, with four bytes followed by a short, and packed my data into it.
One last thing to mention: If you really want to deal with C-style variables using C-style code, the ctypes module is another option. It's made specifically for interacting with C code, so in general it's pretty low-level (and the only module in the standard library that lets you segfault your code), but it let you build some nice mid-level stuff that looks a little more like C:
class ADDRPORT(ctypes.BigEndianStructure):
_fields_ = [("addr", ctypes.c_char*4),
("port", ctypes.c_short)]
addrport = ADDRPORT(addrbytes, portshort)
Since your C code is progressively filling up a buffer, rather than setting elements of a struct, this probably isn't what you want. But it's worth being aware of, because it probably will be what you want at some point.
You almost certainly don't need to call htons and then copy the 2 bytes into a buffer—see Keith's answer for why.
However, if you do need to do this (maybe you're crafting IP packets to compare to captured wire packets as a test or something?), you can.
First, if you're using a bytearray (or anything else that meets the writable buffer protocol), you just use normal list-style slice assignment:
# like C's memcpy(buf+i, foo, 2)
buf[i:i+2] = foo
You don't have that two-byte string foo; you have a short integer. In C, you can turn that into a pointer to two bytes just by using the & operator to get its address, but Python can't do that. Fortunately, there's a standard library module called struct designed for exactly this kind of thing:
t = socket.htons(int(port))
buf[i:i+2] = struct.pack('h', t)
Or, because struct can handle endianness for you:
t = int(port)
buf[i:i+2] = struct.pack('!h', t)
However, often you don't even need the buffer copying; you can define the entire structure all at once inside struct. For example, if you're trying to pack an IP address and port into a 6-byte array, you could do this:
buf = bytearray(6)
i = 0
addrbytes = [int(part) for part in addr.split('.')]
buf[i:i+4] = struct.pack('4B', addrbytes[0], addrbytes[1], addrbytes[2], addrbytes[3])
i += 4
portshort = int(port)
buf[i:i+2] = struct.pack('!h', portshort)
But this is much simpler:
addrbytes = [int(part) for part in addr.split('.')]
portshort = int(port)
buf = struct.pack('!4Bh', addrbytes[0], addrbytes[1], addrbytes[2], addrbytes[3], portshort)
I've just defined a structure that's in network order, with four bytes followed by a short, and packed my data into it.
One last thing to mention: If you really want to deal with C-style variables using C-style code, the ctypes module is another option. It's made specifically for interacting with C code, so in general it's pretty low-level (and the only module in the standard library that lets you segfault your code), but it let you build some nice mid-level stuff that looks a little more like C:
class ADDRPORT(ctypes.BigEndianStructure):
_fields_ = [("addr", ctypes.c_char*4),
("port", ctypes.c_short)]
addrport = ADDRPORT(addrbytes, portshort)
Since your C code is progressively filling up a buffer, rather than setting elements of a struct, this probably isn't what you want. But it's worth being aware of, because it probably will be what you want at some point.
It looks like you are trying to get a port number from user input or a string.
In Python:
port = int(port)
Then you can pass that directly to a socket instantiation:
socket = socket.socket(("127.0.0.1", port))
Python does the htons translation for you. You only need to supply an address to a socket (in the case of TCP) as a tuple of a string and integer.
It is not the equivalent of C memcpy, but if your requirement is to send an object through TCP and reconstruct if at the other side, pickle module is for you.
Is is targetted as storing objects in sequential files or strings and retrieving them, including across different architectures.
Edit : example from The Python Standard Library manual for Python 3.4 :
For the simplest code, use the dump() and load() functions.
import pickle
# An arbitrary collection of objects supported by pickle.
data = {
'a': [1, 2.0, 3, 4+6j],
'b': ("character string", b"byte string"),
'c': set([None, True, False])
}
with open('data.pickle', 'wb') as f:
# Pickle the 'data' dictionary using the highest protocol available.
pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)
The following example reads the resulting pickled data.
import pickle
with open('data.pickle', 'rb') as f:
# The protocol version used is detected automatically, so we do not
# have to specify it.
data = pickle.load(f)
The struct package can do this for you.
import struct
fmt = 'if10p'
data = struct.pack(fmt, 42, 1.234, 'hello')
print struct.unpack(fmt, data)
You have to specify the maximum length of the string (here 10). Your C++ version doesn't work because the raw bytes of a string will contain a pointer rather than the characters inside the sting.