找出消息中发送/接收的特定字节数。 (蟒蛇)

时间:2013-07-15 23:50:45

标签: python sockets packets

这是一个简单的python 3.x TCP服务器:

import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):

    def handle(self):
        self.data = self.request.recv(1024).strip()
        print(str(self.client_address[0]) + " wrote: " + str(self.data.decode()))

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999

    server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()

和客户:

import socket
import sys

HOST, PORT = "localhost", 9999

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))

while( True ):
    data = input("Msg: ")

    if data == "exit()":
        print("Exiting...")
        sock.close()
        exit();

    sock.sendall(bytes(data, "utf-8"))

#numBytes = ....?
#print("Sent: " + str( numBytes ) + " bytes\n")

我无法弄清楚如何查看我在邮件中发送的确切字节数。我可以使用len(数据),但它不考虑null终止符等等....是否也发送了null终止符,还是无关紧要?我尝试研究发送/接收消息的确切字节数,但是我找不到任何特定于python的文档,只看到过使用len()的人的例子,我认为这不是确切的...... < / p>

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

Python字符串中没有空终止符。如果您想发送一个,则必须明确地执行:sock.sendall(bytes(data, "utf-8") + b'\0')

但是,除非您计划将其用作消息之间​​的分隔符,否则没有充分的理由首先添加空终止符。 (请注意,这对于一般的Python字符串不起作用,因为它们允许在中间包含空字节...但是它当然适用于真正的人类可读文本。)

使用空字节作为分隔符并不是一个坏主意......但是您现有的代码需要实际处理它。你不能只是打电话给recv(1024)并假设它是一个完整的信息;你必须继续在循环中调用recv(1024)并附加到缓冲区,直到找到null为止,然后在该循​​环之后将所有内容保存到循环中。


无论如何,sendall方法不返回发送的字节数,因为它总是发送你给它的字节(除非出现错误,在这种情况下是加注)。所以:

buf = bytes(data, "utf-8") + b'\0'
sock.sendall(buf)
bytes_sent = len(buf)

在服务器端,您可能想要编写一个NullTerminatedHandler类,如下所示:

class NullTerminatedHandler(socketserver.BaseRequestHandler):
    def __init__(self):
        self.buf = b''
    def handle(self):
        self.buf += self.request.recv(1024)
        messages = self.buf.split(b'\0')
        for message in messages[:-1]:
            self.handle_message(message)
        self.buf = self.buf[:-1]

然后你可以像这样使用它:

class MyTCPHandler(NullTerminatedHandler):
    def handle_message(self, message):
        print(str(self.client_address[0]) + " wrote: " + str(message.decode()))

虽然我们在这,但你有一些Unicode /字符串问题。从最严重到最不重要:

  • 您几乎不应该只是在没有参数的情况下调用decode。如果您在一侧发送UTF-8数据,则始终在另一侧明确decode('utf-8')
  • decode方法保证会返回str,因此撰写str(message.decode())只会让您的代码感到困惑。
  • 示例代码使用format而不是在一堆对象上调用str并连接它们是有原因的 - 通常它更容易阅读。
  • data.encode('utf-8')bytes(data, 'utf-8')更具可读性。