总结

使用Python的socket和socketserver模块实现ftp文件服务器。不是很难,但在粘包的问题上纠缠了不少时间。解决办法是发送文件信息之后等待一段时间。

 #!/usr/bin/python
#coding:utf-8
'''
ftp文件上传 服务器端
''' import socketserver
import os class myFtpServer(socketserver.BaseRequestHandler):
def setup(self):
pass def handle(self):
dir = r'F:\temp' #存放接收文件的目录 print('Connected %s:%d' %self.client_address)
while True: #持续接收文件
#接收文件的名称和大小
fileInfo = self.request.recv(1024)
if fileInfo.decode('utf-8') == 'exit':
break
filename, filesize = fileInfo.decode('utf-8').strip().split('|')
filePath = os.path.join(dir, filename) #创建文件存放路径
print('Receiving file:%s, filesize:%s'%(filename, filesize))
with open(filePath, 'wb') as f:
recvsize = 0
while True: #持续接收文件内容
if recvsize == int(filesize): #当接收的大小与文件大小相等时结束接收
break
self.data = self.request.recv(1024)
recvsize += len(self.data)
f.write(self.data)
print('upload succeed!!')
print(recvsize)
print('Disconnected %s:%d.' %self.client_address)
'''
def handle(self):
base_path = ''
conn = self.request
print( 'connected...')
while True:
pre_data = conn.recv(1024)
#获取请求方法、文件名、文件大小
file_name,file_size = pre_data.decode('utf-8').split('|') #已经接收文件的大小
recv_size = 0
#上传文件路径拼接
file_dir = os.path.join(base_path,file_name)
f = open(file_dir,'wb')
Flag = True
while Flag:
#未上传完毕,
if int(file_size)>recv_size:
#最多接收1024,可能接收的小于1024
data = conn.recv(1024)
recv_size+=len(data)
#上传完毕,则退出循环
else:
recv_size = 0
Flag = False
#写入文件
f.write(data)
print('upload successed.')
f.close()
def finish(self):
pass '''
if __name__ == '__main__':
addr = ('127.0.0.1', 9999)
sk = socketserver.ThreadingTCPServer(addr, myFtpServer)
sk.serve_forever()
 #!/usr/bin/python
#coding:utf-8
'''
ftp文件上传 客户端
'''
import socket
import sys
import os
import time def ftp(address):
sk = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
sk.connect(address)
while True:
#filePath = r'C:\Users\admin\Desktop\test'
filePath = input('Input file path:')
if filePath == 'exit': #判断退出
sk.send(b'exit')
break
if not os.path.isfile(filePath): #判断是否文件
print('Not available file path...')
continue
filename = os.path.basename(filePath)
#dir = os.path.dirname(filePath) filesize = os.stat(filePath).st_size #获取文件大小
fileInfo = '%s|%s'%(filename, filesize) #重新组织文件信息,包括文件名和文件大小,用‘|’分割 #发送文件信息
sk.send(fileInfo.encode(encoding='utf-8', errors='strict'))
time.sleep(0.01) #为了防止粘包,在文件信息发送之后等待0.01秒 #持续发送文件内容
with open(filePath, 'rb') as f:
sendsize = 0
flag = True
while flag:
if sendsize + 1024 > filesize: #判断最后一份文件内容的读取
data = f.read(filesize - sendsize)
flag = False
else: #一般文件内容的读取
data = f.read(1024)
sendsize += 1024
sk.send(data) sk.close() if __name__ == '__main__':
addr = ('127.0.0.1',9999)
ftp(addr)

环境:python3.5 win10 x64

最新文章

  1. 小白解决CENTOS7错误:Cannot find a valid baseurl for repo: base/7/x86_6
  2. 恢复 混淆后的 stacktrace 文件
  3. Linux常用命令笔记一
  4. Oracle中的数据分页
  5. LA 4255 (拓扑排序 并查集) Guess
  6. JSON Date Format/JSON 日期格式方法分享
  7. 学习嵌入式Linux有没有一个最佳的顺序(持续更新)
  8. Hive和Jdbc示例
  9. 内置函数:filter函数
  10. logback配置信息
  11. Python从入门到放弃Day01
  12. javaweb 与jsp页面的交互流程 (初次接触时写)
  13. ensp 单臂路由实验
  14. Entity Framework Code first(转载)
  15. RGB ECT 4BIT 压缩后质量远高于RGB ETC2 4BIT
  16. visual studio 2017使用技巧
  17. learning at command AT+CEREG
  18. Windows下利用TortoiseSVN搭建本地SVN服务器
  19. mysql中各种join连表查询总结
  20. Java系列:JVM中的OopMap(zz)

热门文章

  1. Laravel 命令行常用命令
  2. Assignment HDU - 2853(二分图匹配 KM 新边旧边)
  3. 51nod_1154 回文串的划分
  4. 多进程的基本使用--multiprocessing 【转】
  5. 小米r3g旧版开发版固件,安装opkg
  6. tomcat缓存
  7. R语言分析朝阳医院数据
  8. 分分钟教你做出自己的新闻阅读APP
  9. Python数据结构之列表、元组及字典
  10. leetcode 【 Majority Element 】python 实现