B.K*_*.K. 2 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()
Run Code Online (Sandbox Code Playgroud)
和客户:
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")
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚如何查看消息中发送的确切字节数。我可以使用len(data),但它不能说明空终止符,因此...。是否也要发送空终止符,还是无关紧要?我尝试研究已发送/已接收消息的确切字节数,但是我找不到任何特定于python的文档,只看到了使用len()的人的示例,我认为这不是确切的...
有任何想法吗?
Python字符串中没有空终止符。如果您想发送一个,则必须明确地执行:sock.sendall(bytes(data, "utf-8") + b'\0')。
但是,没有充分的理由首先添加一个空终止符,除非您打算将其用作消息之间的分隔符。(请注意,这对于一般的Python字符串不起作用,因为允许它们在中间包括空字节…,但是对于真正的人类可读文本当然也可以使用。)
使用空字节作为分隔符不是一个坏主意……但是您现有的代码需要实际处理。您不能只是打电话recv(1024)并假设这是一条完整的消息;您必须继续recv(1024)在循环中调用并追加到缓冲区,直到找到空值为止,然后保存该空值之后的所有内容,以备下次在循环中使用。
无论如何,该sendall方法不会返回发送的字节数,因为它总是准确地发送您给它的字节(除非出现错误,在这种情况下会引发错误)。所以:
buf = bytes(data, "utf-8") + b'\0'
sock.sendall(buf)
bytes_sent = len(buf)
Run Code Online (Sandbox Code Playgroud)
在服务器端,您可能想要编写一个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]
Run Code Online (Sandbox Code Playgroud)
然后,您可以像这样使用它:
class MyTCPHandler(NullTerminatedHandler):
def handle_message(self, message):
print(str(self.client_address[0]) + " wrote: " + str(message.decode()))
Run Code Online (Sandbox Code Playgroud)
在此过程中,您遇到了一些Unicode /字符串问题。从最严重到最严重:
decode带任何参数地打电话。如果要在一侧发送UTF-8数据,请始终在另一侧显式发送decode('utf-8')。decode方法保证返回a str,因此编写str(message.decode())只会使您的代码混乱。format而不是调用str一堆对象并将它们连接在一起的原因-通常更容易阅读。data.encode('utf-8')比更具可读性bytes(data, 'utf-8')。| 归档时间: |
|
| 查看次数: |
2417 次 |
| 最近记录: |