zoukankan      html  css  js  c++  java
  • python_登陆验证文件上传下载_socket

    client.py
    import os
    import sys
    import json
    import struct
    import socket
    
    # 下载--接收文件
    def download(sk):  # 下载
        opt_dic = {'operate':'download'}
        my_send(sk,opt_dic)
        msg = my_recv(sk)
        with open(msg['filename'], 'wb') as f:
            print('File is downloading...')
            while msg['filesize'] > 0:
                content = sk.recv(1024)
                msg['filesize'] -= len(content)
                f.write(content)
            print('File download finished...')
    
    # 上传--传送文件
    def upload(sk):
        opt_dic = {'operate':'upload'}
        my_send(sk,opt_dic)
        path_list=my_recv(sk)['upload_path']
        for index, path in enumerate(path_list,1):
            print(index, path)
        selected_path = input('请输入目的文件夹的序号:')
        uploaded_file = input('请输入本地要上传的文件的全路径:')
        filename = os.path.basename(uploaded_file)
        filesize = os.path.getsize(uploaded_file)
        dic = {'uploaded_path': selected_path, 'filename': filename, 'filesize': filesize}
        my_send(sk,dic)
    
        with open(uploaded_file, mode='rb') as f:
            print('File is uploading...')
            while filesize > 0:
                content = f.read(1024)
                filesize -= len(content)
                sk.send(content)
            print('File upload finished')
    
    
    # 登录
    def login(sk):
        while True:
            usr = input('用户名:').strip()
            pwd = input('密 码 :').strip()
            dic = {'username': usr, 'password': pwd}  # 将用户名和密码放在字典里发过去,而不是单独发送。
            my_send(sk, dic)
            ret = my_recv(sk)
            if ret['operate'] == 'login' and ret['result']:
                print('登录成功')
                break
            else:
                print('登录失败')
    
    # 将 sk.recv(num)封装到函数里:
    # 1-提高复用度;2-每次都使用 struct防止粘包 3;将 server,client实现某一功能的代码对应起来(如,两边都有 download())
    def my_recv(sk):     # 接收
        msg_len = sk.recv(4)
        dic_len = struct.unpack('i', msg_len)[0]
        msg = sk.recv(dic_len).decode('utf-8')
        msg = json.loads(msg)
        return msg
    
    # 将 sk.send(msg)封装到函数里:
    # 1-提高复用度;2-每次都使用 struct防止粘包 3;将 server,client实现某一功能的代码对应起来(如,两边都有 download())
    def my_send(sk,dic):   # 发送 {'username': usr, 'password': pwd} 或者 {'operate':'download'}
        str_dic = json.dumps(dic)   # 网络通信中 一般使用 json而非 pickle
        b_dic = str_dic.encode('utf-8')  # 将 json字符串 encode成 字节串
        mlen = struct.pack('i', len(b_dic))
        sk.send(mlen)  # 4个字节 表示字典转成字节之后的长度
        sk.send(b_dic)  # 具体的字典数据
    
    def exit(sk):
        # sys.exit()
        global flag
        flag = False
        opt_dic = {'operate': 'exit'}
        my_send(sk,opt_dic)
        # sk.close()
    
    
    if __name__ == '__main__':
    
        sk = socket.socket()
        # sk.connect(('192.168.14.109',9012))
        sk.connect(('127.0.0.1',9001))
    
        login(sk)   # 登录
        # 上传下载
        flag=True
        while flag:
            opt_lst = ['upload','download','exit']
            for index,opt in enumerate(opt_lst,1):
                print(index,opt)
            num = int(input('请选择您要操作的序号 :'))
            getattr(sys.modules[__name__],opt_lst[num-1])(sk)
        sk.close()
        # sk.close()
    
    
    server.py (socket版)
    import os
    import sys
    import json
    import struct
    import socket
    import hashlib
    
    # 将 conn.send(msg)封装到函数里,1-提高复用度;2-每次都使用 struct防止粘包
    def my_send(conn,dic):
        str_dic = json.dumps(dic)
        b_dic = str_dic.encode('utf-8')
        mlen = struct.pack('i', len(b_dic))
        conn.send(mlen)  # 4个字节 表示字典转成字节之后的长度
        conn.send(b_dic)  # 具体的字典数据
    
    # download--发送文件
    def download(conn):
        abs_path = r'C:Users12078PycharmProjectsOldBoyDay32登陆验证文件下载_完整版视频文件源位置测试视频.mp4'
        filename = os.path.basename(abs_path)
        filesize = os.path.getsize(abs_path)
        dic = {'filename': filename, 'filesize': filesize}
        my_send(conn,dic)
    
        with open(abs_path, mode='rb') as f:
            while filesize > 0:
                content = f.read(1024)
                filesize -= len(content)
                conn.send(content)
    
    def upload(conn):
        upload_path = ['upload_path1', 'upload_path2']
        my_send(conn,{'upload_path':upload_path})
        file_dic=my_recv(conn)
        file_path = upload_path[int(file_dic['uploaded_path']) - 1] + '\' + file_dic['filename']
        with open(file_path, 'wb') as f:
            while file_dic['filesize'] > 0:
                content = conn.recv(1024)
                file_dic['filesize'] -= len(content)
                f.write(content)
    
    
    # 将 conn.recv(num)封装到函数里,1-提高复用度;2-每次都使用 struct防止粘包
    def my_recv(conn):
        msg_len = conn.recv(4)
        dic_len = struct.unpack('i', msg_len)[0]
        msg = conn.recv(dic_len).decode('utf-8')
        msg = json.loads(msg)  # 网网络通信中使用较多的是json而不是pickle
        return msg
    
    # 将密码进行加密,使用username作为 salt
    def get_md5(username,password):
        md5 = hashlib.md5(username.encode('utf-8'))
        md5.update(password.encode('utf-8'))
        return md5.hexdigest()
    
    # 登录
    def login(conn):
        flag = True
        while flag:
            msg = my_recv(conn)  # 接收到的是 dic = {'username': usr, 'password': pwd}
            with open('userinfo') as f:
                for line in f:
                    name, pwd = line.strip().split('|')
                    if name == msg['username'] and pwd == get_md5(name, msg['password']):
                        res, flag = True, False
                        break
                else:
                    res = False
                dic = {'operate': 'login', 'result': res}
                my_send(conn, dic)  # 将登录结果发送给 client
    
    def exit(conn):
        # sys.exit()
        # sk.close()
        global flag
        flag = False
        conn.close()  # 只断开和客户端的连接,不关闭服务。
    
    
    
    if __name__ == '__main__':
    
    
        sk = socket.socket()
        sk.bind(('127.0.0.1',9001))
        sk.listen()
    
        while True:  # 允许和多个客户端连接(非并行)
            conn,_ =sk.accept()
            # 有了一个客户端来连接你
            login(conn)
    
            flag = True
            while flag:
                # 接收消息,根据用户的选择进行上传/下载操作
                opt_dic = my_recv(conn)  # {'operate':'download'} 或 {'operate':'upload'}
                if hasattr(sys.modules[__name__],opt_dic['operate']):
                    getattr(sys.modules[__name__],opt_dic['operate'])(conn)
    
            # conn.close()
        sk.close()
    
    
    server.py(socketserver版)
    import os
    import sys
    import json
    import struct
    import hashlib
    import socketserver
    
    class Myserver(socketserver.BaseRequestHandler):
        def handle(self):
            conn = self.request
            login(conn)
            flag = True
            while flag:  # 不需要更外层的那个 while了,和多个客户端通讯的任务交给了socketserver.
                try:
                    # 接收消息,根据用户的选择进行上传/下载操作
                    opt_dic = my_recv(conn)  # {'operate':'download'} 或 {'operate':'upload'} ,{'operate':'exit'}
                    if hasattr(sys.modules[__name__], opt_dic['operate']):
                        getattr(sys.modules[__name__], opt_dic['operate'])(conn)
                        if opt_dic['operate']=='exit': flag=False  # 这样做判断,虽然破坏了 反射的简介,但【只有这样】才能退出连接。
                except ConnectionResetError:  # 处理异常断开连接,比如客户端非正常退出。
                    break
            conn.close()  # 只断开和客户端的连接,不关闭服务。
    
    
    # 将 conn.send(msg)封装到函数里,1-提高复用度;2-每次都使用 struct防止粘包; 3-每次 send/recv都struct一下。
    def my_send(conn,dic):
        str_dic = json.dumps(dic)
        b_dic = str_dic.encode('utf-8')
        mlen = struct.pack('i', len(b_dic))
        conn.send(mlen)  # 4个字节 表示字典转成字节之后的长度
        conn.send(b_dic)  # 具体的字典数据
    
    # download--发送文件
    def download(conn):
        abs_path = r'C:Users12078PycharmProjectsOldBoyDay32登陆验证文件下载_完整版视频文件源位置测试视频.mp4'
        filename = os.path.basename(abs_path)
        filesize = os.path.getsize(abs_path)
        dic = {'filename': filename, 'filesize': filesize}
        my_send(conn,dic)
    
        with open(abs_path, mode='rb') as f:
            while filesize > 0:
                content = f.read(1024)
                filesize -= len(content)
                conn.send(content)
    
    def upload(conn):
        upload_path = ['upload_path1', 'upload_path2']
        my_send(conn,{'upload_path':upload_path})
        file_dic=my_recv(conn)
        file_path = upload_path[int(file_dic['uploaded_path']) - 1] + '\' + file_dic['filename']
        with open(file_path, 'wb') as f:
            while file_dic['filesize'] > 0:
                content = conn.recv(1024)
                file_dic['filesize'] -= len(content)
                f.write(content)
    
    
    # 将 conn.recv(num)封装到函数里,1-提高复用度;2-每次都使用 struct防止粘包; 3-每次 send/recv都struct一下。
    def my_recv(conn):
        msg_len = conn.recv(4)
        dic_len = struct.unpack('i', msg_len)[0]
        msg = conn.recv(dic_len).decode('utf-8')
        msg = json.loads(msg)  # 网网络通信中使用较多的是json而不是pickle
        return msg
    
    # 将密码进行加密,使用username作为 salt
    def get_md5(username,password):
        md5 = hashlib.md5(username.encode('utf-8'))
        md5.update(password.encode('utf-8'))
        return md5.hexdigest()
    
    # 登录
    def login(conn):
        flag = True
        while flag:
            msg = my_recv(conn)  # 接收到的是 dic = {'username': usr, 'password': pwd}
            with open('userinfo') as f:
                for line in f:
                    name, pwd = line.strip().split('|')
                    if name == msg['username'] and pwd == get_md5(name, msg['password']):
                        res, flag = True, False
                        break
                else:
                    res = False
                dic = {'operate': 'login', 'result': res}
                my_send(conn, dic)  # 将登录结果发送给 client
    
    
    def exit(conn):
        # sys.exit()
        # sk.close()
        # global flag
        # flag  = False
        conn.close()  # 只断开和客户端的连接,不关闭服务。
    
    
    
    if __name__ == '__main__':
        flag = True
        server = socketserver.ThreadingTCPServer(('127.0.0.1', 9001), Myserver)
        server.serve_forever()
    
    
  • 相关阅读:
    Java面向对象
    Java方法
    Java控制语句
    Java接收用户键盘输入
    Java运算符
    Java类型转换
    Java的加载与执行
    Java关键字
    Java常见的DOS命令及JDK
    nginx学习要点记录
  • 原文地址:https://www.cnblogs.com/Collin-pxy/p/13034187.html
Copyright © 2011-2022 走看看