【测试环境】
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
3、Socket Programming HOWTO
*** walker的流水账 ***