tcp协议之recv
Posted walle-zhao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tcp协议之recv相关的知识,希望对你有一定的参考价值。
写一个下载功能的时候遇到的一个bug。
import socket import struct import json import os base_dir = os.getcwd() print(base_dir) client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(("127.0.0.1", 8889)) while True: msg = input(">>:") if not msg: continue client.send(msg.encode("utf-8")) heard_data = client.recv(4) heard_len = struct.unpack("i", heard_data)[0] heard_bytes = client.recv(heard_len) heard = json.loads(heard_bytes.decode("utf-8")) filename = heard["filename"] md5 = heard["md5"] filesize = heard["filesize"] data = b"" recv_size = 0 while filesize > 0: # 判断条件为什么不能使用while filesize > 0: msg = client.recv(1024) print(len(msg)) data += msg filesize -= 1024 # 这里的一个问题,为什么不能使用filesize -= 1024 with open("{}/test/downloads/{}".format(base_dir, filename), "wb") as f: f.write(data) print("下载成功") client.close()
import socket import os import struct import json base_dir = os.getcwd() server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(("127.0.0.1", 8889)) server.listen(5) while True: client,address = server.accept() while True: try: cmd_recv = client.recv(1024) if not cmd_recv: break cmd = cmd_recv.decode("utf-8") filename = cmd.split()[1] filesize = os.path.getsize("{}/test/share/{}".format(base_dir, filename)) print(filesize) heard = { "filename": filename, "filesize": filesize, "md5": "xxxx", } heard_str = json.dumps(heard) heard_len = struct.pack("i", len(heard_str)) client.send(heard_len) client.send(heard_str.encode("utf-8")) with open("{}/test/share/{}".format(base_dir, filename), "rb") as f: for line in f: client.send(line) except Exception as e: print(e) break client.close() server.close()
这里是客户端的问题,就是在recv的时候,每次接收1024个,但是实际上可能发送的并没有1024个,这个时候recv并不会一直等待着,而在一定的时间之后能接受多少先接收多少。
所以,这里在print(len(msg))的时候,就会发现中间有一些是没有达到1024个字符。
因此下面filesize -= 1024就是错误的。改正过来的客户端代码如下:
import socket import struct import json import os base_dir = os.getcwd() print(base_dir) client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(("127.0.0.1", 8889)) while True: msg = input(">>:") if not msg: continue client.send(msg.encode("utf-8")) heard_data = client.recv(4) heard_len = struct.unpack("i", heard_data)[0] heard_bytes = client.recv(heard_len) heard = json.loads(heard_bytes.decode("utf-8")) filename = heard["filename"] md5 = heard["md5"] filesize = heard["filesize"] data = b"" recv_size = 0 while filesize > 0: # 判断条件为什么不能使用while filesize > 0: msg = client.recv(1024) data += msg filesize -= len(msg) # 这里的一个问题,为什么不能使用filesize -= 1024 with open("{}/test/downloads/{}".format(base_dir, filename), "wb") as f: f.write(data) print("下载成功") client.close()
以上是关于tcp协议之recv的主要内容,如果未能解决你的问题,请参考以下文章
深入理解TCP协议及其源代码——send和recv背后数据的收发过程
TCP/IP应用层协议实现 - 数据收发send/recv(lwip)
TCP/IP应用层协议实现 - 数据收发send/recv(lwip)