Python tcp socket 传送文件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python tcp socket 传送文件相关的知识,希望对你有一定的参考价值。
【测试环境】
os:Windows 10 x64 Python:3.6.3
【server.py】
#encoding: utf-8 #author: walker #date: 2017-12-01 #summary: 用socket创建tcp server以接收文件 import os, time import socket import struct cur_dir_fullpath = os.path.dirname(os.path.abspath(__file__)) Host = '127.0.0.1' Port = 6789 BufSize = 8196 FmtHead = '256sHL' #L决定单个文件必须小于4G FmtHeadLen = struct.calcsize(FmtHead) DstRoot = os.path.join(cur_dir_fullpath, 'output') #目标目录 StartTime = time.time() #开始时间 def ProcAll(): cnt = 0 fileSizeTotal = 0 sockServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sockServer.bind((Host, Port)) print('Listen prot %d ...' % Port) sockServer.listen(1) sock, addr = sockServer.accept() print('local: %s:%d' % (sock.getsockname())) print('client: %s:%d' % addr) while True: #接收数据包头(相对路径,相对路径长度,文件大小) pkgHead = sock.recv(FmtHeadLen) relPath, relPathLen, fileSize = struct.unpack(FmtHead, pkgHead) relPath = relPath.decode('utf8')[0:relPathLen] if relPath == 'OVER' and fileSize == 0: print('All file recv over!') break pathfile = os.path.join(DstRoot, relPath) dstDir = os.path.dirname(pathfile) if not os.path.exists(dstDir): os.makedirs(dstDir) with open(pathfile, mode='wb') as f: recvSize = 0 #单文件已接收数据量 while True: if recvSize >= fileSize: break bufSize = BufSize if fileSize - recvSize < BufSize: #剩余数据量小于BufSize bufSize = fileSize - recvSize buf = sock.recv(bufSize) f.write(buf) recvSize += len(buf) fileSizeTotal += recvSize cnt += 1 print('cnt: %d, time cost: %.2fs, %s'% (cnt, time.time()-StartTime, pathfile)) sock.close() sockServer.close() print('cnt: %d, time total: %.2fs, send bytes:%ld B'% (cnt, time.time()-StartTime, fileSizeTotal)) if __name__ == '__main__': ProcAll() print('Time total:%.2fs' % (time.time() - StartTime))
【client.py】
#encoding: utf-8 #author: walker #date: 2017-12-01 #summary: 用socket连接tcp server以传送文件 import os, time import socket import struct cur_dir_fullpath = os.path.dirname(os.path.abspath(__file__)) Host = '127.0.0.1' Port = 6789 BufSize = 8196 FmtHead = '256sHL' #L决定单个文件必须小于4G SrcRoot = os.path.join(cur_dir_fullpath, 'input') #源目录 ExtSet = {'.pdf', '.html', '.htm'} #后缀列表 StartTime = time.time() #开始时间 def ProcAll(): cnt = 0 fileSizeTotal = 0 sockClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print('Connect %s:%d ...' % (Host, Port)) sockClient.connect((Host, Port)) print('local: %s:%d' % (sockClient.getsockname())) for parent, dirnames, filenames in os.walk(SrcRoot): for filename in filenames: if os.path.splitext(filename)[1].lower() not in ExtSet: #排除非指定后缀的文件 continue pathfile = os.path.join(parent, filename) relPath = pathfile[len(SrcRoot):].strip(os.path.sep) #相对路径(相对于SrcRoot) fileSize = os.path.getsize(pathfile) #发送数据包头(相对路径,相对路径长度,文件大小) pkgHead = struct.pack(FmtHead, relPath.encode('utf8'), len(relPath), fileSize) sockClient.sendall(pkgHead) with open(pathfile, mode='rb') as f: while True: buf = f.read(BufSize) if len(buf) < 1: break sockClient.sendall(buf) fileSizeTotal += fileSize cnt += 1 print('cnt: %d, time cost: %.2fs, %s'% (cnt, time.time()-StartTime, pathfile)) #发送文件传送结束消息 pkgHead = struct.pack(FmtHead, 'OVER'.encode('utf8'), len('OVER'), 0) sockClient.sendall(pkgHead) sockClient.close() print('cnt: %d, time total: %.2fs, send bytes:%ld B'% (cnt, time.time()-StartTime, fileSizeTotal)) if __name__ == '__main__': ProcAll() print('Time total:%.2fs' % (time.time() - StartTime))
【相关阅读】
1、struct
2、socket
*** walker的流水账 ***
以上是关于Python tcp socket 传送文件的主要内容,如果未能解决你的问题,请参考以下文章
网络通信中TCP出现的黏包以及解决方法 socket 模拟黏包
python twisted 写tcp 客户端 服务器 为啥self.transport.write传送多数据的时候,接受到是一起接受呢