多线程FTP(1)——多线程网络通信简单实现
之前写了一个FTP项目,但实际上我们写的FTP项目只满足单线程——这就像是打电话一样,当一个客户端和服务端连接,其他客户端就会因为服务端占线而无法连接,必须等之前连接的客户端“挂断”才能连接通信。
就像演示的一样,
- 当一个客户端完成连接(比如说登录,和查看当前目录时)
- 另一个客户端无法完成和服务端的通信,比如说登录;
- 而只有在前一个客户端断开连接,服务端才会去处理后一个客户端的信息(即完成登录)
很显然,一次只满足一个用户登录并不满足我们需求,我们想要的肯定是可以允许多个用户登录,服务端同时处理多个用户命令的FTP项目。
于是,我们想到了多线程的的方法去实现多个用户同时登录。
什么是多线程
多线程
threading ,利用 CPU 和 IO 可以同时执行的原来,让 CPU 不会干巴巴等待 IO 完成。
个人理解
单线程
多线程
简单来说,多线程就是一个计算机的统筹处理事情的操作,遇到需要等待的事情,就“先去”(在等待的同时)做可以即时做的事情。(理论上,多线程会增加CPU的内存和计算操作,但具体会增加多少,我没有研究过)
thread 版本
服务端
import socket, threading, time
def create():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 8080))
server.listen(5)
while True: # 连接循环
conn, addr = server.accept()
t = threading.Thread(target=connection, args=(conn, ))
t.start()
def connection(conn):
while True: # 通信循环
data = conn.recv(1024)
print(data.decode("utf-8"))
now = time.localtime()
now_time = time.strftime("%Y年%m月%d日%H时%M分%S秒", now)
conn.send(now_time.encode("utf-8"))
# args 是函数的参数,如果有参数,传入的一定是一个元组
t = threading.Thread(target=create)
t.start() # 不要忘记 start,表示启动线程
客户端
客户端没有什么变化
import socket, time
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 8080))
while True:
cmd = input(">>: ").strip()
client.send(cmd.encode("utf-8"))
time.sleep(10) # 休息10秒,为了更好的演示,客户端B 并没有休眠 10 秒
data = client.recv(1024)
print(data.decode("utf-8"))
socketserver 版本
服务端
import socketserver,time
class server(socketserver.BaseRequestHandler):
def handle(self) -> None: # 一定要是 handle
print(self.request) # 相当于 conn
print(self.client_address) # 相当于 addr
while True: # 通信循环
msg = self.request.recv(1024)
now = time.localtime()
now_time = time.strftime("%Y年%m月%d日%H时%M分%S秒", now)
print(msg.decode("utf-8"), now_time)
now = time.localtime()
now_time = time.strftime("%Y年%m月%d日%H时%M分%S秒", now)
self.request.send(now_time.encode("utf-8"))
s = socketserver.ThreadingTCPServer(("127.0.0.1", 8080), server) # 开启 TCP服务 多线程
s.serve_forever()
客户端
没有什么变化。