网络并发通信

基于threading的多线程网络并发

代码实现 : day9/thread_server.py

实现步骤

  1. 创建监听套接字
  2. 循环接收客户端连接请求
  3. 当有新的客户端连接创建线程处理客户端请求
  4. 主线程继续等待其他客户端连接
  5. 当客户端退出,则对应分支线程退出
"""
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. 功能
    【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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值