from socket import *
importsysimporttime#实现各种功能请求
classTftpClient(object):def __init__(self,sockfd):
self.sockfd=sockfddefdo_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 infiles:print(file)print("文件展示完毕")else:#请求失败原因
print(data)#下载指定文件
defdo_get(self,filename):
self.sockfd.send(('G' +filename).encode())
data= self.sockfd.recv(1024).decode()#请求成功
if data == 'OK':
fd= open(filename,'wb')whileTrue:
data= self.sockfd.recv(1024)#结束符
if data == b'##':breakfd.write(data)
fd.close()print("%s 下载完成\n"%filename)else:#请求失败原因
print(data)defdo_put(self,filename):#判断本地是否有要上传的文件
try:
fd= open(filename,'rb')except:print("上传文件不存在")returnself.sockfd.send(("P"+filename).encode())
data= self.sockfd.recv(1024).decode()#请求成功
if data == 'OK':whileTrue:
data= fd.read(1024)if notdata:breakself.sockfd.send(data)
fd.close()#发送结束符并防止粘包
time.sleep(0.1)
self.sockfd.send(b'##')print("%s 上传完毕"%filename)else:#请求失败原因
print(data)#创建套接字并建立连接
defmain():#终端输入地址
if len(sys.argv) < 3:print("argv is error")returnHOST= sys.argv[1]
PORT= int(sys.argv[2])
ADDR=(HOST,PORT)
sockfd=socket()
sockfd.connect(ADDR)#创建对象
tftp =TftpClient(sockfd)whileTrue: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()
多线程并发
threading模块完成多线程并发
对比多进程并发
优势 :
资源消耗少
缺点 :
需要注意对共享资源的操作
实现步骤:1. 创建套接字,绑定,监听2. 接收客户端连接请求,创建新的线程3. 主线程继续等待其他客户端连接,分支线程执行客户端具体请求4. 处理完客户端请求后分支线程自然退出,关闭客户端套接字
示例:from socket import *
importos,sysfrom threading import *HOST= "0.0.0.0"PORT= 8888ADDR=(HOST,PORT)#客户端处理函数
defhandler(connfd):print("Connect from",connfd.getpeername())whileTrue:
data= connfd.recv(1024).decode()if notdata:break
print(data)
connfd.send(b'Receive your msg')
connfd.close()defmain(ADDR):
s=socket()
s.bind(ADDR)
s.listen(5)whileTrue:try:
connfd,addr=s.accept()#处理 Ctrl + C
exceptKeyboardInterrupt:
s.close()
sys.exit("服务器退出")#其他异常
exceptException as e:print(e)continue
#创建子线程用于处理客户端请求
t = Thread(target=handler,args=(connfd,))
t.setDaemon(True)
t.start()if __name__ == __main__:
main()