基于threading的多线程网络并发
代码实现 : day9/thread_server.py
实现步骤
- 创建监听套接字
- 循环接收客户端连接请求
- 当有新的客户端连接创建线程处理客户端请求
- 主线程继续等待其他客户端连接
- 当客户端退出,则对应分支线程退出
"""
thread_server.py 基于threading多线程并发
重点代码
"""
from socket import *
from threading import Thread
import sys
# 全局变量
HOST = '0.0.0.0'
PORT = 8888
ADDR = (HOST,PORT)
# 处理客户端请求
def handle(c):
while True:
data = c.recv(1024)
if not data:
break
print(data.decode())
c.send(b'OK')
c.close()
# 创建tcp套接字
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(ADDR)
s.listen(3)
print("Listen the port 8888...")
# 循环接收客户端链接
while True:
try:
c,addr = s.accept()
print("Connect from",addr)
except KeyboardInterrupt:
sys.exit('服务器退出')
except Exception as e:
print(e)
continue
# 创建线程处理
t = Thread(target=handle,args=(c,))
t.setDaemon(True) # 主线程退出其他线程也退出
t.start()
ftp 文件服务器
代码实现 : day9/ftp
- 功能
【1】 分为服务端和客户端,要求可以有多个客户端同时操作。
【2】 客户端可以查看服务器文件库中有什么文件。
【3】 客户端可以从文件库中下载文件到本地。
【4】 客户端可以上传一个本地文件到文件库。
【5】 使用print在客户端打印命令输入提示,引导操作
"""
ftp文件处理
env: python3.6
多线程并发 & socket
"""
from socket import *
from threading import Thread
import sys,os
import time
# 全局变量
HOST = '0.0.0.0'
PORT = 8080
ADDR = (HOST,PORT)
FTP = "/home/tarena/FTP/" # 文件库位置
# 实现文件传输的具体功能
class FTPServer(Thread):
def __init__(self,connfd):
super().__init__()
self.connfd = connfd
# 处理文件列表发送
def do_list(self):
# 获取文件列表
file_list = os.listdir(FTP)
if not file_list:
self.connfd.send('文件库为空'.encode()) #19
return
else:
self.connfd.send(b'OK') #19
time.sleep(0.1)
# 发送文件列表
files = '\n'.join(file_list)
self.connfd.send(files.encode())
# 文件下载
def do_retr(self,filename):
try:
f = open(FTP+filename,'rb')
except Exception:
self.connfd.send('文件不存在'.encode())
return
else:
self.connfd.send(b'OK')
time.sleep(0.1)
# 发送文件
while True:
data = f.read(1024)
if not data:
time.sleep(0.1)
self.connfd.send(b'##')
break
self.connfd.send(data)
f.close()
# 处理上传文件
def do_stor(self,filename):
if os.path.exists(FTP + filename):
self.connfd.send("文件已存在".encode())
return
else:
self.connfd.send(b'OK')
# 接收文件
f = open(FTP+filename,'wb')
while True:
data = self.connfd.recv(1024)
if data == b'##':
# 文件发送完
break
f.write(data)
f.close()
def run(self):
while True:
# 接收客户端请求
data = self.connfd.recv(1024).decode()
if not data or data == 'QUIT':
return # 线程结束
elif data == 'LIST':
self.do_list()
elif data[:4] == 'RETR':
filename = data.split(' ')[-1]
self.do_retr(filename)
elif data[:4] == 'STOR':
filename = data.split(' ')[-1]
self.do_stor(filename)
# 搭建网络模型
def main():
# 创建tcp套接字
s = socket()
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
s.bind(ADDR)
s.listen(3)
print("Listen the port 8080...")
# 循环接收客户端链接
while True:
try:
c, addr = s.accept()
print("Connect from", addr)
except KeyboardInterrupt:
sys.exit('服务器退出')
except Exception as e:
print(e)
continue
# 创建线程处理
t = FTPServer(c)
t.setDaemon(True) # 主线程退出其他线程也退出
t.start()
if __name__ == '__main__':
main()
"""
ftp 文件服务 客户端
"""
from socket import *
import sys,time
# 服务器地址
ADDR = ('127.0.0.1',8080)
# 客户端处理类
class FTPClient:
def __init__(self,sockfd):
self.sockfd = sockfd
# 获取文件列表
def do_list(self):
self.sockfd.send(b'LIST') # 发送请求 29
# 等待回复
data = self.sockfd.recv(128).decode()
if data == 'OK':
# 一次接收所有文件名称字符串(解决沾包)
data = self.sockfd.recv(1024 * 1024 * 10)
print(data.decode())
else:
print(data)
def do_retr(self,filename):
# 发送请求
self.sockfd.send(('RETR '+filename).encode())
# 等待回复
data = self.sockfd.recv(128).decode()
if data == 'OK':
f = open(filename,'wb')
# 循环接收
while True:
data = self.sockfd.recv(1024)
if data == b'##':
# 文件发送完
break
f.write(data)
f.close()
else:
print(data)
def do_stor(self,filename):
try:
f = open(filename,'rb')
except Exception:
print("文件不存在")
return
# 提取文件名称
filename = filename.split('/')[-1]
# 发送请求
self.sockfd.send(('STOR ' + filename).encode())
# 等待回复
data = self.sockfd.recv(128).decode()
if data == 'OK':
while True:
data = f.read(1024)
if not data:
time.sleep(0.1)
self.sockfd.send(b'##')
break
self.sockfd.send(data)
f.close()
else:
print(data)
def do_quit(self):
self.sockfd.send(b'QUIT')
self.sockfd.close()
sys.exit('谢谢使用')
# 网络链接
def main():
sockfd = socket()
try:
sockfd.connect(ADDR)
except Exception as e:
print(e)
return
ftp = FTPClient(sockfd) # 调用请求功能
# 循环的发送请求
while True:
print("==========命令选项============")
print("***** LIST *****")
print("***** STOR filename *****")
print("***** RETR filename *****")
print("***** QUIT *****")
print("=============================")
cmd = input("命令:")
if cmd == 'LIST':
ftp.do_list()
elif cmd[:4] == 'RETR':
filename = cmd.split(' ')[-1]
ftp.do_retr(filename)
elif cmd[:4] == 'STOR':
filename = cmd.split(' ')[-1]
ftp.do_stor(filename)
elif cmd == 'QUIT':
ftp.do_quit()
else:
print("请输入正确命令!")
if __name__ == '__main__':
main()