客户端

core文件夹

from lib import common
from conf import setting
import os

userinfo = {'cookies': None}

def register(client):
    while True:
        username = input('请输入用户名:').strip()
        password = input('请输入密码:').strip()
        re_password = input('请确认密码:').strip()
        if password == re_password:
            send_dic = {
                'username': username,
                'password': password,
                'user_type': 'admin',
                'func_type': 'register'
            }
            back_dic = common.send_and_back(send_dic, client)
            if back_dic.get('flag'):
                print(back_dic.get('msg'))
                break
            else:
                print(back_dic.get('msg'))
        else:
            print('两次密码不一致!!!')
            continue


def login(client):
    while True:
        username = input('请输入用户名:').strip()
        password = input('请输入密码:').strip()
        send_dic = {
            'username': username,
            'password': password,
            'func_type': 'login'
        }
        back_dic = common.send_and_back(send_dic, client)

        if back_dic.get('flag'):
            print(back_dic.get('msg'))
            userinfo['cookies'] = back_dic.get('session')
            break
        else:
            print(back_dic.get('msg'))


def upload_movie(client):
    while True:
        upload_movie_dir = setting.UPLOAD_MOVIE_PATH
        movie_list = os.listdir(upload_movie_dir)
        if not movie_list:
            print('没有电影可以上传')
            break
        for index, movie_name in enumerate(movie_list):
            print(index, movie_name)
        choice = input('请输入电影编号或q退出:').strip()
        if choice == 'q':
            break
        if not choice.isdigit():
            print('请输入数字!!!')
            continue
        choice = int(choice)
        if choice not in range(len(movie_list)):
            print('请输入编号内数字!!!')
            continue

        movie_name = movie_list[choice]
        movie_path = os.path.join(upload_movie_dir, movie_name)
        movie_size = os.path.getsize(movie_path)
        movie_md5 = common.get_movie_md5(movie_path)
        send_dic = {
            'func_type': 'check_movie',
            'movie_md5': movie_md5,
            'cookies': userinfo.get('cookies')
        }
        back_dic = common.send_and_back(send_dic, client)
        if back_dic.get('flag'):
            choice2 = input('请输入是否是收费的(y or n):').strip()
            is_free = 0
            if choice2 == 'y':
                is_free = 1
            send_dic2 = {
                'func_type': 'upload_movie',
                'movie_md5': movie_md5,
                'cookies': userinfo.get('cookies'),
                'movie_name': movie_name,
                'movie_size': movie_size,
                'is_free': is_free
            }
            back_dic2 = common.send_and_back(send_dic2, client, file=movie_path)
            if back_dic2.get('flag'):
                print(back_dic2.get('msg'))
                break
        else:
            print(back_dic.get('msg'))


def delete_movie(client):
    while True:
        send_dic = {
            'func_type': 'get_movie_list',
            'cookies': userinfo.get('cookies'),
            'movie_type': 'all'
        }
        back_dic = common.send_and_back(send_dic, client)
        if not back_dic.get('flag'):
            print(back_dic.get('msg'))
            break
        movie_list = back_dic.get('movie_list')
        for index, movie_name_id in enumerate(movie_list):
            print(index, movie_name_id)
        if not movie_list:
            print('没有可删除的电影了')
            break
        choice = input('请输入需要删除的电影编号或q退出:').strip()
        if choice == 'q':
            break
        if not choice.isdigit():
            continue
        choice = int(choice)
        if choice not in range(len(movie_list)):
            continue
        movie_name_id = movie_list[choice]
        send_dic = {
            'func_type': 'delete_movie',
            'cookies': userinfo.get('cookies'),
            'movie_id': movie_name_id[1]
        }
        back_dic2 = common.send_and_back(send_dic, client)
        if back_dic2.get('flag'):
            print(back_dic2.get('msg'))
            break


def send_notice(client):
    title = input('请输入公告标题:').strip()
    content = input('请输入公告内容:').strip()
    send_dic = {
        'title': title,
        'content': content,
        'cookies': userinfo.get('cookies'),
        'func_type': 'send_notice'
    }
    back_dic = common.send_and_back(send_dic, client)
    print(back_dic.get('msg'))


func_dic = {
    '1': register,
    '2': login,
    '3': upload_movie,
    '4': delete_movie,
    '5': send_notice,
}


def admin_view(client):
    while True:
        print('''
        1.注册
        2.登录
        3.上传视频
        4.删除视频
        5.发布公告
        q.退出
        ''')
        choice = input('请输入功能编号:').strip()
        if choice == 'q':
            break
        if choice not in func_dic:
            print('请输入功能内编号!!!')
            continue
        func_dic[choice](client)
admin.py
from lib import common
from conf import setting
import time
import os

user_info = {'cookies': None, 'is_vip': 0}


def register(client):
    while True:
        username = input('请输入用户名:').strip()
        password = input('请输入密码:').strip()
        re_password = input('请确认密码:').strip()
        if password == re_password:
            send_dic = {
                'username': username,
                'password': password,
                'user_type': 'user',
                'func_type': 'register'
            }
            back_dic = common.send_and_back(send_dic, client)
            if back_dic.get('flag'):
                print(back_dic.get('msg'))
                break
            else:
                print(back_dic.get('msg'))


def login(client):
    while True:
        username = input('请输入用户名:').strip()
        password = input('请输入密码:').strip()
        send_dic = {
            'func_type': 'login',
            'username': username,
            'password': password
        }
        back_dic = common.send_and_back(send_dic, client)
        if back_dic.get('flag'):
            print(back_dic.get('msg'))
            user_info['cookies'] = back_dic.get('session')
            is_vip = back_dic.get('is_vip')
            if is_vip:
                user_info['is_vip'] = is_vip
            break
        else:
            print(back_dic.get('msg'))


def buy_vip(client):
    if not user_info.get('is_vip'):
        choice = input('请输入y确认冲会员(会员费10000元),输入其他键退出:').strip()
        if choice == 'y':
            send_dic = {
                'cookies': user_info.get('cookies'),
                'func_type': 'buy_vip'
            }
            back_dic = common.send_and_back(send_dic, client)
            print(back_dic.get('msg'))
            login(client)
        else:
            print('穷b!!!')
    else:
        print('您已经是会员了')


def check_movies(client):
    send_dic = {
        'func_type': 'get_movie_list',
        'movie_type': 'all',
        'cookies': user_info.get('cookies')
    }
    back_dic = common.send_and_back(send_dic, client)
    if back_dic.get('flag'):
        print(back_dic.get('movie_list'))

    else:
        print(back_dic.get('msg'))


def download_free_movie(client):
    while True:
        send_dic = {
            'func_type': 'get_movie_list',
            'movie_type': 'free',
            'cookies': user_info.get('cookies')
        }
        back_dic = common.send_and_back(send_dic, client)
        if not back_dic.get('flag'):
            print(back_dic.get('msg'))
            break
        movie_list = back_dic.get('movie_list')
        if not movie_list:
            print('没有可下载的免费的电影')
            break
        for index, movie_id_name in enumerate(movie_list):
            print(index, movie_id_name)
        choice = input('请输入要下载的电影编号').strip()
        if not choice.isdigit():
            print('请输入数字')
            continue
        choice = int(choice)
        if choice not in range(len(movie_list)):
            print('请输入编范围内的数字')
            continue
        movie_name, movie_id, movie_type = movie_list[choice]
        send_dic2 = {
            'cookies': user_info.get('cookies'),
            'func_type': 'download_movie',
            'movie_id': movie_id,
            'movie_name': movie_name
        }
        back_dic2 = common.send_and_back(send_dic2, client)
        wait_time = back_dic2.get('wait_time')
        if wait_time:
            print('广告时间10s')
        time.sleep(wait_time)
        movie_size = back_dic2.get('movie_size')
        movie_path = os.path.join(setting.DOWNLOAD_MOVIE_PATH, movie_name)
        recv_data = 0
        with open(movie_path, 'wb') as f:
            while recv_data < movie_size:
                data = client.recv(1024)
                f.write(data)
                recv_data += len(data)
        break


def download_pay_movie(client):
    while True:
        send_dic = {
            'cookies': user_info.get('cookies'),
            'func_type': 'get_movie_list',
            'movie_type': 'pay'
        }
        back_dic = common.send_and_back(send_dic, client)
        if not back_dic.get('flag'):
            print(back_dic.get('msg'))
            break
        movie_list = back_dic.get('movie_list')
        if not movie_list:
            print('没有可下载的电影')
            break
        for index, movie_name_id in enumerate(movie_list):
            print(index, movie_name_id)
        choice = input('请输入y确认购买电影(会员:200元,普通用户800元),输入其他退出:').strip()
        if choice == 'y':
            if user_info.get('is_vip'):
                print('会员购买电影成功,开始选择电影...')
            else:
                print('普通用户购买电影成功,开始选择电影...')
        else:
            print('穷b, 没钱还想看电影,滚犊子吧')
            break
        choice2 = input('请输入需要下载电影的编号:').strip()
        if not choice2.isdigit():
            continue
        choice2 = int(choice2)
        if choice2 not in range(len(movie_list)):
            continue
        movie_name, movie_id, movie_type = movie_list[choice2]
        send_dic2 = {
            'cookies': user_info.get('cookies'),
            'func_type': 'download_movie',
            'movie_name': movie_name,
            'movie_id': movie_id
        }
        back_dic2 = common.send_and_back(send_dic2, client)
        movie_size = back_dic2.get('movie_size')
        movie_path = os.path.join(setting.DOWNLOAD_MOVIE_PATH, movie_name)
        recv_data = 0
        with open(movie_path, 'wb') as f:
            while recv_data < movie_size:
                data = client.recv(1024)
                f.write(data)
                recv_data += len(data)
        break


def check_download_record(client):
    send_dic = {
        'func_type': 'check_download_record',
        'cookies': user_info.get('cookies')
    }
    back_dic = common.send_and_back(send_dic, client)
    if back_dic.get('flag'):
        print(back_dic.get('download_movie_list'))
    else:
        print(back_dic.get('msg'))


def check_notice(client):
    send_dic = {
        'func_type': 'check_notice',
        'cookies': user_info.get('cookies')
    }
    back_dic = common.send_and_back(send_dic, client)
    if back_dic.get('flag'):
        print(back_dic.get('notice_list'))
    else:
        print(back_dic.get('msg'))


func_dic = {
    '1': register,
    '2': login,
    '3': buy_vip,
    '4': check_movies,
    '5': download_free_movie,
    '6': download_pay_movie,
    '7': check_download_record,
    '8': check_notice
}


def user_view(client):
    while True:
        print('''
        1 注册
        2 登录
        3 冲会员
        4 查看视频
        5 下载免费视频
        6 下载收费视频
        7 查看下载记录
        8 查看公告
        q 退出
        ''')
        choice = input('请输入功能编号:').strip()
        if choice == 'q':
            break
        if choice not in func_dic:
            continue
        func_dic[choice](client)
user.py

lib文件夹

import struct
import hashlib
import json
import os


def send_and_back(send_dic, client, file=None):
    # 发送报头和真实数据
    json_bytes = json.dumps(send_dic).encode('utf-8')
    header = struct.pack('i', len(json_bytes))
    client.send(header)
    client.send(json_bytes)
    if file:
        with open(file, 'rb') as f:
            for i in f:
                client.send(i)

    # 接收服务端返回的数据
    headers = client.recv(4)
    bytes_len = struct.unpack('i', headers)[0]
    json_bytes_data = client.recv(bytes_len).decode('utf8')
    back_dic = json.loads(json_bytes_data)
    return back_dic

def get_movie_md5(movie_path):
    movie_size = os.path.getsize(movie_path)
    index_list = [0, movie_size//3, (movie_size//3)*2, movie_size-10]
    md5_obj = hashlib.md5()
    with open(movie_path, 'rb') as f:
        for line in index_list:
            f.seek(line)
            data = f.read(10)
            md5_obj.update(data)
    return md5_obj.hexdigest()
common.py

服务端

interface文件夹

from db.models import Movie
from db.models import Notice
import datetime
from lib import common
from threading import Lock
from conf import setting
import os

mutex = Lock()


@common.login_auth
def check_movie_interface(back_dic, conn):
    movie_md5 = back_dic.get('movie_md5')

    movie_obj_list = Movie.select_data(movie_md5=movie_md5)
    if movie_obj_list:
        send_dic = {
            'flag': False, 'msg': '电影已经存在!!'
        }
    else:
        send_dic = {'flag': True, 'msg': '可以继续上传'}
    common.send_data(send_dic, conn)


@common.login_auth
def upload_movie_interface(back_dic, conn):
    # 保证电影的名字唯一性
    movie_name = common.get_session() + back_dic.get('movie_name')
    movie_path = os.path.join(setting.MOVIE_DIR, movie_name)
    movie_size = back_dic.get('movie_size')
    recv_data = 0
    with open(movie_path, 'wb') as f:
        while recv_data < movie_size:
            data = conn.recv(1024)
            f.write(data)
            recv_data += len(data)
    movie_obj = Movie(
        movie_name=movie_name,
        movie_size=movie_size,
        movie_md5=back_dic.get('movie_md5'),
        is_free=back_dic.get('is_free'),
        is_delete=0,
        upload_time=str(datetime.datetime.now()),
        user_id=back_dic.get('user_id'))
    movie_obj.insert_data()
    send_dic = {
        'flag': True, 'msg': '电影上传成功'
    }
    common.send_data(send_dic, conn)


@common.login_auth
def delete_movie_interface(back_dic, conn):
    movie_id = back_dic.get('movie_id')
    movie_obj = Movie.select_data(m_id=movie_id)[0]
    movie_obj.is_delete = 1
    movie_obj.update_data()
    send_dic = {
        'flag': True,
        'msg': '电影删除成功'
    }
    common.send_data(send_dic, conn)


@common.login_auth
def send_notice_interface(back_dic, conn):
    notice_obj = Notice(
        title=back_dic.get('title'),
        content=back_dic.get('content'),
        create_time=str(datetime.datetime.now()),
        user_id=back_dic.get('user_id'))
    notice_obj.insert_data()
    send_dic = {
        'msg': '公告发布成功'
    }
    common.send_data(send_dic, conn)
admin_interface.py
from lib import common
from db.models import Movie, DownLoadRecord
from db.models import User
from db import user_data
import datetime
from threading import Lock
from conf import setting
import os

mutex = Lock()


# 未删除电影接口
@common.login_auth
def get_movie_list_interface(back_dic, conn):
    movie_obj_list = Movie.select_data()
    if movie_obj_list:
        movie_list = []
        for movie_obj in movie_obj_list:
            if not movie_obj.is_delete:
                if back_dic.get('movie_type') == 'all':
                    movie_list.append([movie_obj.movie_name, movie_obj.m_id, '免费电影' if movie_obj.is_free else '收费电影'])

                elif back_dic.get('movie_type') == 'free':
                    if movie_obj.is_free:
                        movie_list.append([movie_obj.movie_name, movie_obj.m_id, '免费电影'])
                else:
                    if not movie_obj.is_free:
                        movie_list.append([movie_obj.movie_name, movie_obj.m_id, '收费电影'])

        send_dic = {
            'flag': True, 'movie_list': movie_list
        }
    else:
        send_dic = {
            'flag': False, 'msg': '服务端没有电影'
        }
    common.send_data(send_dic, conn)


def register_interface(back_dic, conn):
    username = back_dic.get('username')
    user_obj_list = User.select_data(user_name=username)
    if user_obj_list:
        send_dic = {
            'flag': False, 'msg': '用户已存在!'
        }
    else:
        pwd = common.get_md5(back_dic.get('password'))
        user_obj = User(
            user_name=username,
            user_pwd=pwd,
            user_type=back_dic.get('user_type'),
            register_time=str(datetime.datetime.now())
        )
        user_obj.insert_data()
        send_dic = {
            'flag': True, 'msg': f'用户{username}注册成功'
        }
    common.send_data(send_dic, conn)


def login_interface(back_dic, conn):
    user_obj = User.select_data(user_name=back_dic.get('username'))[0]
    if not user_obj:
        send_dic = {'flag': False, 'msg': '用户不存在'}
    else:
        if user_obj.user_pwd == common.get_md5(back_dic.get('password')):
            addr = back_dic.get('addr')
            session = common.get_session()
            mutex.acquire()
            user_data.user_online[addr] = [session, user_obj.user_id]
            mutex.release()
            send_dic = {
                'flag': True, 'msg': '登录成功!', 'session': session
            }
            if user_obj.is_vip:
                send_dic['is_vip'] = user_obj.is_vip
        else:
            send_dic = {'flag': False, 'msg': '密码错误!!!'}
    common.send_data(send_dic, conn)


@common.login_auth
def download_movie_interface(back_dic, conn):
    user_id = back_dic.get('user_id')
    user_obj = User.select_data(user_id=user_id)[0]
    movie_name = back_dic.get('movie_name')
    movie_path = os.path.join(setting.MOVIE_DIR, movie_name)
    send_dic = {
        'movie_size': os.path.getsize(movie_path),
        'wait_time': 0
    }
    if not user_obj.is_vip:
        send_dic['wait_time'] = 10
    common.send_data(send_dic, conn, file=movie_path)
    download_obj = DownLoadRecord(
        movie_id=back_dic.get('movie_id'),
        user_id=user_id,
        download_time=str(datetime.datetime.now())
    )
    download_obj.insert_data()
common_interface.py
from db.models import User, DownLoadRecord, Movie, Notice
from lib import common


@common.login_auth
def buy_vip_interface(back_dic, conn):
    user_id = back_dic.get('user_id')
    user_obj = User.select_data(user_id=user_id)[0]
    user_obj.is_vip = 1
    user_obj.update_data()
    send_dic = {'msg': '充值会员成功,请重新登录'}
    common.send_data(send_dic, conn)


@common.login_auth
def check_download_record_interface(back_dic, conn):
    user_id = back_dic.get('user_id')
    down_load_obj_list = DownLoadRecord.select_data(user_id=user_id)
    if not down_load_obj_list:
        send_dic = {
            'flag': False, 'msg': '没有下载记录'
        }
    else:
        download_list = []
        for download_obj in down_load_obj_list:
            movie_id = download_obj.movie_id
            movie_obj = Movie.select_data(m_id=movie_id)[0]
            download_list.append([movie_obj.movie_name, download_obj.download_time])
        send_dic = {
            'flag': True, 'download_movie_list': download_list
        }
    common.send_data(send_dic, conn)


@common.login_auth
def check_notice_interface(back_dic, conn):
    notice_obj_list = Notice.select_data()
    if not notice_obj_list:
        send_dic = {
            'flag': False, 'msg': '暂无公告'
        }
        common.send_data(send_dic, conn)
    else:
        notice_list = []
        for notice_obj in notice_obj_list:
            notice_list.append([notice_obj.title, notice_obj.content, notice_obj.create_time])
        send_dic = {
            'flag': True, 'notice_list': notice_list
        }
    common.send_data(send_dic, conn)
user_interface.py

lib文件夹

import struct
import json
import hashlib
import uuid
from threading import Lock
from db.user_data import user_online
mutex = Lock()

def send_data(back_dic, conn, file=None):
    bytes_data = json.dumps(back_dic).encode('utf-8')
    header = struct.pack('i', len(bytes_data))
    conn.send(header)
    conn.send(bytes_data)
    if file:
        with open(file, 'rb') as f:
            for i in f:
                conn.send(i)

def get_md5(pwd):
    md5_obj = hashlib.md5()
    md5_obj.update(pwd.encode('utf-8'))
    salt = '天王盖地虎'
    md5_obj.update(salt.encode('utf-8'))
    return md5_obj.hexdigest()


def get_session():
    uuid_str = str(uuid.uuid4())
    session_val = get_md5(uuid_str)
    return session_val


def login_auth(func):
    def inner(*args, **kwargs):  # args = (back_dic, conn)
        client_session = args[0].get('cookies')
        addr = args[0].get('addr')

        mutex.acquire()
        # 'addr': [session, user_obj.user_id]
        session_id_list = user_online.get(addr)
        mutex.release()
        if session_id_list:
            if client_session == session_id_list[0]:
                args[0]['user_id'] = session_id_list[1]
                res = func(*args, **kwargs)
                return res
            else:
                send_dic = {'flag': False, 'msg': '携带session值错误'}
                send_data(send_dic, args[1])
        else:
            send_dic = {'flag': False, 'msg': '用户未登录,没有执行权限'}
            send_data(send_dic, args[1])

    return inner
common.py

tcp_server文件夹

from interface import admin_interface
from interface import common_interface
from interface import user_interface
import socket
import struct
import json
from concurrent.futures import ThreadPoolExecutor
from threading import Lock
from db import user_data
mutex = Lock()
pool = ThreadPoolExecutor(50)

func_dic = {'register': common_interface.register_interface,
            'login': common_interface.login_interface,
            'check_movie': admin_interface.check_movie_interface,
            'upload_movie': admin_interface.upload_movie_interface,
            'get_movie_list': common_interface.get_movie_list_interface,
            'delete_movie': admin_interface.delete_movie_interface,
            'send_notice': admin_interface.send_notice_interface,
            'buy_vip': user_interface.buy_vip_interface,
            'download_movie': common_interface.download_movie_interface,
            'check_download_record': user_interface.check_download_record_interface,
            'check_notice': user_interface.check_notice_interface}




def working(conn, addr):
    while True:
        try:
            headers = conn.recv(4)
            bytes_len = struct.unpack('i', headers)[0]

            json_data = conn.recv(bytes_len).decode('utf-8')
            back_dic = json.loads(json_data)
            # 保证每个客户端过来都是唯一的,将addr添加到客户端发过来的字典中
            back_dic['addr'] = str(addr)

            func_type = back_dic.get('func_type')
            if func_type in func_dic:
                func_dic[func_type](back_dic, conn)
        except Exception as e:
            print(e)
            # 清除当前客户端存放在服务端的session值
            mutex.acquire()
            user_data.user_online.pop(str(addr))
            mutex.release()
            break
    conn.close()

def run():
    server = socket.socket()
    server.bind(('127.0.0.1', 9876))
    server.listen(50)
    while True:
        conn, addr = server.accept()
        print(addr)
        # 异步提交任务
        pool.submit(working, conn, addr)
socket_server.py
12-27 07:52