import socket sk = socket.socket() sk.bind(("192.16.12.3",8088)) sk.listen() conn,addr = sk.accept() conn.send(b""/"".encode("utf-8")) ret = conn.recv(1024) print(ret.decode("utf-8")) conn.close() sk.close() import socket sk = socket.socket() sk.connect(("192.16.12.3",8088)) sk.send(b""/encode("utf-8")) ret = sk.recv(1024) print(ret.decode("utf-8")) sk.close()
以上是网络传输tcp协议的标准模式.
关于解决tcp传输文件中的黏包问题:
服务器端:
import socket import json import struct sk = socket.socket() sk.bind(("127.0.0.1",8001)) sk.listen() conn,addr = sk.accept() b_len_dic = conn.recv(4) len_dic = struct.unpack('i',b_len_dic)[0]# 获取到int类型字典的长度, # unpack得到的是一个元组,要取下标为0的位置 str_dic = conn.recv(len_dic).decode('utf-8') # str_dic = {"opt":menu.get(num),"filename":None,"filesize":None} dic = json.loads(str_dic) if dic["opt"] == "upload": filename = "1"+ dic["filename"] with open(filename,"ab") as f: while dic['filesize']: content = conn.recv(1024) f.write(content) dic['filesize'] -= len(content) conn.close() sk.close()
客户端:
import socket import os import json import struct sk = socket.socket() sk.connect(("127.0.0.1",8001)) menu = {"1":"upload","2":"download"} for k,v in menu.items(): print(k,v) num = input("请输入功能选项:") if num == "1": dic = {"opt":menu.get(num),"filename":None,"filesize":None} file_path = input("请输入一个绝对路径:")# 文件的绝对路径 # E:Python S14day32实现大文件的传输11.mp4 filename = os.path.basename(file_path)# 文件名字 filesize = os.path.getsize(file_path)# 获取用户输入的路径中文件的大小 dic["filename"] = filename dic["filesize"] = filesize str_dic = json.dumps(dic) len_dic = len(str_dic)# 获取到字典的长度,是一个int类型的数据 46 146 b_len_dic = struct.pack('i',len_dic)# 用一个4bytes的数据表示字典的长度 sk.send(b_len_dic + str_dic.encode("utf-8"))# 将bytes类型的字典的长度 + bytes类型的字典的内容,一起发送给服务器 # 因为上边send字典时,如果程序执行过快,可能会马上执行到下边的send(content) # 此时有可能会发生粘包,所以在此中间加一个recv,为了避免粘包 with open(file_path,"rb") as f: while filesize: content = f.read(1024) sk.send(content) filesize -= len(content)
需要注意的是struct模块的unpack解包得到的是只含一个传入结果的元组,可以利用索引提取出来.