这是一个简单的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>
有什么想法吗?
答案 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')
更具可读性。