ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

多进程并发模型--TFTP文件服务器

2021-01-11 19:01:21  阅读:319  来源: 互联网

标签:-- self filename print sockfd 服务器 TFTP data connfd


1、项目功能

  【客户端】

    客户端有简单的页面命令提示 ,功能包含

      【1】查看服务器文件库中的文件列表(普通文件)

      【2】可以下载其中的某个文件到本地

      【3】可以上传客户端文件到服务器文件库

  【服务端】

    服务器需求

      【1】允许多个客户端同时操作

      【2】每个客户端可能回连续发送命令

2、技术分析

  【1】tcp套接字更适合文件传输

  【2】并发方案 ---> fork 多进程并发

  【3】对文件的读写操作

  【4】获取文件列表 ----> os.listdir()

  【5】粘包的处理

3、整体结构设计

  【1】服务器功能封装在类中(上传,下载,查看列表)

  【2】创建套接字,流程函数调用 main()

  【3】① 客户端负责发起请求,接受回复,展示

      ② 服务端负责接受请求,逻辑处理

4、编程实现

  【1】搭建整体结构,创建网络连接

  【2】创建多进程和类的结构

  【3】每个功能模块的实现

【TFTP-server.py】
from socket import * import os import signal import sys import time #文件库 FILE_PATH = "/home/tarena/" #实现功能模块 class TftpServer(object): def __init__(self,connfd): self.connfd = connfd def do_list(self): #获取列表 file_list = os.listdir(FILE_PATH) if not file_list: self.connfd.send("文件库为空".encode()) return else: self.connfd.send(b'OK') time.sleep(0.1) files = "" for file in file_list: if os.path.isfile(FILE_PATH+file) and \ file[0] != '.': files = files + file + '#' self.connfd.send(files.encode()) def do_get(self,filename): try: fd = open(FILE_PATH + filename,'rb') except: self.connfd.send("文件不存在".encode()) return self.connfd.send(b'OK') time.sleep(0.1) #发送文件 try: while True: data = fd.read(1024) if not data: break self.connfd.send(data) except Exception as e: print(e) time.sleep(0.1) self.connfd.send(b'##') #表示文件发送完成 print("文件发送完毕") def do_put(self,filename): try: fd = open(FILE_PATH+filename,'wb') except: self.connfd.send("无法上传".encode()) return self.connfd.send(b'OK') while True: data = self.connfd.recv(1024) if data == b'##': break fd.write(data) fd.close() print("文件上传完毕") #流程控制,创建套接字,创建并发,方法调用 def main(): HOST = '0.0.0.0' PORT = 8888 ADDR = (HOST,PORT) sockfd = socket() sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) sockfd.bind(ADDR) sockfd.listen(5) signal.signal(signal.SIGCHLD,signal.SIG_IGN) while True: try: connfd,addr = sockfd.accept() except KeyboardInterrupt: sockfd.close() sys.exit("服务器退出") except Exception as e: print(e) continue print("客户端登录:",addr) #创建父子进程 pid = os.fork() if pid == 0: sockfd.close() tftp = TftpServer(connfd) # __init__传参 while True: data = connfd.recv(1024).decode() if (not data) or data[0] == 'Q': print("客户端退出") sys.exit(0) elif data[0] == "L": tftp.do_list() elif data[0] == 'G': filename = data.split(' ')[-1] tftp.do_get(filename) elif data[0] == 'P': filename = data.split(' ')[-1] tftp.do_put(filename) else: print("客户端发送错误指令") else: connfd.close() continue if __name__ == "__main__": main()

 

【TFTP-client.py】
from socket import * import sys import time #实现各种功能请求 class TftpClient(object): def __init__(self,sockfd): self.sockfd = sockfd def do_list(self): self.sockfd.send(b'L') #发送请求类型 #接收服务器回应 data = self.sockfd.recv(1024).decode() if data == "OK": data = self.sockfd.recv(4096).decode() files = data.split('#') for file in files: print(file) print("文件展示完毕") else: #请求失败原因 print(data) def do_get(self,filename): self.sockfd.send(('G ' + filename).encode()) data = self.sockfd.recv(1024).decode() if data == 'OK': fd = open(filename,'wb') while True: data = self.sockfd.recv(1024) if data == b'##': break fd.write(data) fd.close() print("%s 下载完成\n"%filename) else: print(data) def do_put(self,filename): try: fd = open(filename,'rb') except: print("上传文件不存在") return self.sockfd.send(("P "+filename).encode()) data = self.sockfd.recv(1024).decode() if data == 'OK': while True: data = fd.read(1024) if not data: break self.sockfd.send(data) fd.close() time.sleep(0.1) self.sockfd.send(b'##') print("%s 上传完毕"%filename) else: print(data) #创建套接字建立连接 def main(): if len(sys.argv) < 3: print("argv is error") return HOST = sys.argv[1] PORT = int(sys.argv[2]) ADDR = (HOST,PORT) sockfd = socket() sockfd.connect(ADDR) tftp = TftpClient(sockfd) #__init__是否需要传参 while True: print("") print("==========命令选项===========") print("********** list *********") print("********** get file ******") print("********** put file ******") print("********** quit *********") print("=============================") cmd = input("输入命令>>") if cmd.strip() == "list": tftp.do_list() elif cmd[:3] == "get": filename = cmd.split(' ')[-1] tftp.do_get(filename) elif cmd[:3] == "put": filename = cmd.split(' ')[-1] tftp.do_put(filename) elif cmd.strip() == "quit": sockfd.send(b'Q') sockfd.close() sys.exit("欢迎使用") else: print("请输入正确命令!") if __name__ == "__main__": main()

 

标签:--,self,filename,print,sockfd,服务器,TFTP,data,connfd
来源: https://www.cnblogs.com/longyuu/p/14263738.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有