到目前为止,在我的项目中,我一直使用以下解决方案来下载数据。数据量很小,所以没有问题:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('192.168.0.10', 6100)
sock.connect(server_address)
sock.send(*** here is command to server***)
data = sock.recv(1024)
sock.close()
现在,我需要从服务器下载大量数据,结果发现我的解决方案只检索了其中的一部分。我读到问题可能是 TCP 数据包的最大大小。我尝试使用以下代码解决它:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('192.168.0.10', 6100)
sock.connect(server_address)
sock.send((*** here is command to server***)
data = b''
while True:
try:
chunk = sock.recv(1024)
except Exception as e:
print(e)
if not chunk:
chunk = str(repr(data.decode()))
sock.close()
break
data += chunk
print(f"Received data: {data}")
该循环的工作原理是将数据流的连续部分添加到“data”。不幸的是,当数据完成后,脚本挂起。我做错了什么?
我应该提到我无法控制服务器。我只能通过请求从中获取现成的数据包。我无法控制它向我发送数据包的部分内容。一切都必须发生在我这边,即客户端。 数据包总是以“\x00”结尾我可以用它吗?
这是一个简单的基于套接字的客户端/服务器程序的示例。
这里我们使用哨兵(EOT)来表示所有数据已经传输完毕。显然,只有在保证重要数据不包含 EOT 字符的情况下才能做到这一点。 客户端将发送 5,000 字节。服务器将接收
最多2,048 字节的数据块。 接收到的数据将被累积并打印总长度。该数字应与传输的数据大小相匹配。
注意事件的使用。这很重要,因为理论上客户端可能会在服务器侦听和接受连接之前尝试连接。
from socket import socket, AF_INET, SOCK_STREAM
from threading import Thread, Event
BUFSIZ = 2048
HOST_PORT = "localhost", 6667
EOT = b"\x04"
def server(event):
with socket(AF_INET, SOCK_STREAM) as s:
s.bind(HOST_PORT)
s.listen()
event.set()
c, _ = s.accept()
all_data = b""
while data := c.recv(BUFSIZ):
if data[-1] != ord(EOT):
all_data += data
else:
all_data += data[:-1]
break
print(len(all_data))
if __name__ == "__main__":
event = Event()
(thread := Thread(target=server, args=(event,))).start()
message = b"x" * 5000
event.wait()
with socket(AF_INET, SOCK_STREAM) as s:
s.connect(HOST_PORT)
s.sendall(message+EOT)
thread.join()