<p>您几乎肯定不需要调用<code>htons</code>,然后将2个字节复制到一个缓冲区中,请参阅Keith的答案。</p>
<p>但是,如果您需要这样做(也许您正在制作IP包以与捕获的有线包进行比较,作为测试或其他什么?),你可以。</p>
<p>首先,如果您使用的是<code>bytearray</code>(或任何满足可写缓冲区协议的内容),那么只需使用普通的<code>list</code>样式的片分配:</p>
<pre><code># like C's memcpy(buf+i, foo, 2)
buf[i:i+2] = foo
</code></pre>
<p>你没有两个字节的字符串<code>foo</code>;你有一个短整数。在C语言中,只需使用<code>&</code>操作符获取地址,就可以将其转换为指向两个字节的指针,但Python不能这样做。幸运的是,有一个名为<a href="http://docs.python.org/3/library/struct.html" rel="noreferrer">^{<cd6>}</a>的标准库模块正是为这种情况而设计的:</p>
<pre><code>t = socket.htons(int(port))
buf[i:i+2] = struct.pack('h', t)
</code></pre>
<p>或者,因为<code>struct</code>可以为您处理endianness:</p>
<pre><code>t = int(port)
buf[i:i+2] = struct.pack('!h', t)
</code></pre>
<p>然而,通常您甚至不需要缓冲区复制;您可以在<code>struct</code>中一次定义整个结构。例如,如果要将IP地址和端口打包到6字节数组中,可以执行以下操作:</p>
<pre><code>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)
</code></pre>
<p>但这要简单得多:</p>
<pre><code>addrbytes = [int(part) for part in addr.split('.')]
portshort = int(port)
buf = struct.pack('!4Bh', addrbytes[0], addrbytes[1], addrbytes[2], addrbytes[3], portshort)
</code></pre>
<p>我刚刚定义了一个按网络顺序排列的结构,四个字节后跟一个短字节,并将数据打包到其中。</p>
<p>最后要提的是:如果您真的想使用C样式代码处理C样式变量,<a href="http://docs.python.org/3/library/ctypes.html" rel="noreferrer">ctypes</a>模块是另一个选项。它是专门为与C代码交互而设计的,所以一般来说它是非常低级的(也是标准库中唯一一个允许您对代码进行分段的模块),但是它可以让您构建一些看起来更像C:</p>
<pre><code>class ADDRPORT(ctypes.BigEndianStructure):
_fields_ = [("addr", ctypes.c_char*4),
("port", ctypes.c_short)]
addrport = ADDRPORT(addrbytes, portshort)
</code></pre>
<p>因为您的C代码正在逐渐地填充缓冲区,而不是设置<code>struct</code>的元素,所以这可能不是您想要的。但这是值得注意的,因为它可能会是你在某个时候想要的。</p>