zoukankan      html  css  js  c++  java
  • 网络编程(sock)搞定!

    前些日子写了一个网络编程的,纯新手,能优化的地方很多!但是,也算自己独立完成了这么一个东西,晚上发上来!!

    socket_project

    项目结构:

    │ readme
    │ 原理图.png

    ├─.idea
    │ │ misc.xml
    │ │ modules.xml
    │ │ workspace.xml
    │ │ 网络编程.iml
    │ │
    │ └─inspectionProfiles
    ├─client
    │ ├─bin
    │ │ start.py
    │ │
    │ ├─conf_c
    │ │ │ info_c.py
    │ │ │
    │ │ └─__pycache__
    │ │ info_c.cpython-35.pyc
    │ │
    │ ├─core
    │ │ │ main.py
    │ │ │
    │ │ └─__pycache__
    │ │ main.cpython-35.pyc
    │ │
    │ └─file_position
    └─server
    ├─bin
    │ start.py

    ├─conf
    │ │ info.py
    │ │ __init__.py
    │ │
    │ └─__pycache__
    │ info.cpython-35.pyc
    │ __init__.cpython-35.py

    ├─core
    │ │ main.py
    │ │
    │ └─__pycache__
    │ main.cpython-35.pyc

    ├─file_position
    │ │ 1.mp4
    │ │
    │ └─ncp
    └─user_db
    auth_file

    README

    功能:
    用户加密认证
    每个用户有自己的家目录,且只能访问自己的家目录
    对用户进行磁盘配额,每个用户的可用空间不同
    允许用户在ftp server上随意切换目录
    允许用户查看当前目录下的文件
    允许上传和下载文件,并保证文件的一致性
    文件传输过程中显示进度条
    附加:支持文件的断点续传
    开发的程序需符合PEP8开发规范,及专业的生产软件设计规范,包括目录、代码命名、功能接口等
    
    user_dic = {'ncp':'123123','cpp':'321321','tesla':'222222'}
    测试用的两个文件,一个视频文件放在服务端的共享目录:file_position,测试文件在客户端的file_position的ncp下,一个文件小于20M一个大于
    用户磁盘配额说明:total_package = {'ncp':count_size(20),'cpp':count_size(10),'tesla':count_size(50)}
    ncp:20M   cpp:10M    tesla:50M
    
    1.用户密码通过hash的md5算法加密
    2.这里没有采用多线程或者多进程,后期可加
    3.用户有自己的家目录,用ls查看自己家目录下的文件
    4.用户可以用cd path完成路径切换,path为你要切换的目录(注意,如果cd后不加空格就输入会报错)
    5.磁盘配完成
    6.用户可以上传、下载并且包头用了md5随机加密,每次操作md5不一样
    6.能显示进度条,client使用get下载文件时,并且可以断定续传,原理相同,没有在put上实现
    7.自己强化的功能就是client可以使用大部分DOS命令对服务端进行操作
    说明
    #author:nie cheng ping
    # _*_ coding=gbk _*_
    from client.conf_c import info_c
    import hashlib
    import socket
    import struct
    import json
    import os
    import sys
    import math
    import time
    
    class FTPclient:
        socket_net = info_c.socket_net
        socket_type = info_c.socket_type
        package_recv = info_c.package_size
        str_code = info_c.coding
        file_path = info_c.file_path_c
    
        def __init__(self,server_ip_port,connection=True):
            self.socket = socket.socket(self.socket_net,self.socket_type)
            self.server_ip_port = server_ip_port
            if connection:
                self.connection()
            else:
                self.close_line()
    
        def connection(self):
            self.socket.connect(self.server_ip_port)
            print(self.server_ip_port)
    
        def close_line(self):
            self.socket.close()
    
        def progress(self, recvd, total):
            fraction = '{:.0%}'.format(recvd / total)
            sys.stdout.write('
    [%-30s] %s' % ('#' * int(math.floor(recvd * 30 / total)),fraction))
            sys.stdout.flush()
            if recvd == total:
                sys.stdout.write('
    ')
    
        def run_commands(self,inp):
            if not inp: return
            header = self.socket.recv(4)
            header_json_len = struct.unpack('i',header)[0]
            header_json = json.loads(self.socket.recv(header_json_len).decode(self.str_code))
            data_len = header_json['package_size']
            recv_data = b''
            recv_size = 0
            while recv_size < data_len:
                recv_data += self.socket.recv(self.package_recv)
                recv_size += self.package_recv
            print(recv_data.decode(self.str_code))
            return
    
        def get(self,user):
            header = self.socket.recv(4) # 接收报头长度
            print(header)
            header_json_len = struct.unpack('i',header)[0] # 根据报头长度拆分报头
            # 获取报头中的报头信息
            header_bytes = self.socket.recv(header_json_len)
    
            header_bytes_json = header_bytes.decode(self.str_code)
            # decode得到报文头内容,再反序列化
            header_json_dic = json.loads(header_bytes_json)
            print(header_json_dic)
            data_len = header_json_dic['file_size'] # data_len 等于总的数据长度
            share_file = os.path.join(self.file_path,user,header_json_dic['filename'])
            if os.path.exists(share_file):
                with open(share_file,'rb')as f:
                    data = f.read()              # data 等于断后现有的数据大小
                    if len(data) < data_len:
                        recv_size = 0
                        while recv_size < len(data):
                            recv_data = self.socket.recv(self.package_recv)
                            recv_size += len(recv_data)
                            self.progress(recv_size,len(data))
                    with open(share_file,'ab+')as f:
                        f.seek(len(data))
                        recv_data = b''
                        recv_size = len(data)
                        while recv_size < data_len:
                            recv_data = self.socket.recv(self.package_recv)
                            recv_size += len(recv_data)
                            f.write(recv_data)
                            self.progress(recv_size,data_len)
                        return
    
            with open(share_file,'wb')as f:
                recv_size = 0
                while recv_size < data_len:
                    recv_data = self.socket.recv(self.package_recv)
                    f.write(recv_data)
                    recv_size += len(recv_data)
                    self.progress(recv_size,data_len)
    
        def put(self,inp,user,header):
            cmd = inp.split()
            share_file = os.path.join(self.file_path,user,cmd[1])
            send_size = 0
            with open(share_file,'rb')as f:
                for i in f:
                    self.socket.send(i)
                    send_size += len(i)
                    self.progress(send_size,header['file_size'])
                else:
                    print('send ok')
    
        def summary(self):
            while True:
                hash_data = hashlib.md5()
    
                data_user = self.socket.recv(self.package_recv)
                print(data_user.decode(self.str_code))
                inp_user = input('>>')
                self.socket.send(inp_user.encode(self.str_code))
    
                data_pass = self.socket.recv(self.package_recv)
                print(data_pass.decode(self.str_code))
                inp_password = input('>>')
                hash_data.update(inp_password.encode(self.str_code))
                self.socket.send(hash_data.hexdigest().encode(self.str_code))
    
                data_recv = self.socket.recv(self.package_recv)
                if data_recv.decode(self.str_code) == 'ok':
                    user_file_dir = os.path.join(self.file_path,inp_user)
    
                    if not os.path.exists(user_file_dir):
                        os.mkdir(user_file_dir)
                    while True:
                        inp = input('>>')
                        if not inp: continue
                        cmd = inp.split()
                        while True:
                            if cmd[0] == 'get':
                                self.socket.send(inp.encode(self.str_code))
                                self.get(inp_user)
                            # 上次要设置用户在server端的磁盘大小空间,所以验证全在这里
                            elif cmd[0] == 'put':
                                share_file = os.path.join(self.file_path, inp_user, cmd[1])
                                if not os.path.exists(share_file):
                                    print('file is not found')
                                    break
                                self.socket.send(inp.encode(self.str_code))
                                header = {'filename': share_file,
                                          'file_size': os.path.getsize(share_file),
                                          'md5': info_c.hash_data.hexdigest()}
                                header_json = json.dumps(header)
                                header_json_bytes = header_json.encode(self.str_code)
                                header_struct = struct.pack('i', len(header_json_bytes))
                                self.socket.send(header_struct)
                                self.socket.send(header_json_bytes)
                                data = self.socket.recv(self.package_recv)
                                if data.decode(self.str_code) == 'ok':
                                    self.put(inp,inp_user,header)
                                else:
                                    print(data.decode(self.str_code))
                                    break
                            else:
                                self.socket.send(inp.encode(self.str_code))
                                self.run_commands(inp)
                            break
                if data_recv.decode(self.str_code) == 'authentication is false':
                    print(data_recv.decode(self.str_code))
                    continue
    #author:nie cheng ping
    # _*_ coding=gbk _*_
    import os
    import socket
    import hashlib
    import json
    import random
    import string
    
    ftp_path = 'file_position'
    user_db_file = 'user_db'
    auth_name = 'auth_file'
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    user_db_path = os.path.join(base_dir,user_db_file)
    auth_file = os.path.join(user_db_path,auth_name)
    ftp_s_home = os.path.join(base_dir,ftp_path)
    package_size = 4096
    socket_net = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    listen_line = 5
    coding = 'gbk'
    
    md5_data = ''.join(random.sample(string.digits,6))
    hash_data = hashlib.md5()
    hash_data.update(md5_data.encode(coding))
    
    
    def count_size(number):
        number_bytes = number*1024*1024
        return number_bytes
    total_package = {'ncp':count_size(20),'cpp':count_size(10),'tesla':count_size(50)}
    
    
    def create_auth():
        user_name = ('ncp','cpp','tesla')
        user_dic = {'ncp':'123123','cpp':'321321','tesla':'222222'}
        hash_data = hashlib.md5()
        hash_list = []
        for i in user_name:
            hash_data.update(user_dic[i].encode('gbk'))
            hash_list.append(hash_data.hexdigest())
        user_auth = {'ncp':hash_list[0],'cpp':hash_list[1],'tesla':hash_list[2]}
        print(user_auth)
    
        with open(auth_file,'w')as fw:
            fw.write(json.dumps(user_auth))
            fw.close()
    
    def authentication(data):
        with open(auth_file,'r')as fr:
            user_info = json.loads(fr.read())
            fr.close()
        if data[0] in user_info and data[1] == user_info[data[0]]:
            print('authentication is successful')
            return True
        else:
            return False
    server_conf info.py
    #author:nie cheng ping
    # _*_ coding=gbk _*_
    import os
    import struct
    import json
    import socket
    from server.conf import info
    from server.conf.info import authentication
    import re
    
    class FTPserver:
        ftps_file = info.ftp_s_home
        package_size_tra = info.package_size
        str_code = info.coding
        listen = info.listen_line
        socket_net = info.socket_net
        socket_type = info.socket_type
    
    
        def __init__(self,server_ip_port,bind_active=True):
            self.server = server_ip_port
            self.socket = socket.socket(self.socket_net,self.socket_type)
            if bind_active:
                self.bind()
                self.listen_line()
            else:
                self.close_line()
    
        def bind(self):
            self.socket.bind(self.server)
            self.server_ip_port = self.socket.getsockname()
    
        def listen_line(self):
            self.socket.listen(self.listen)
    
        def wait_line(self):
            return self.socket.accept()
    
        def close_line(self):
            self.socket.close()
    
        def run_commands(self,cmd,user,path,active=True):
            if active:
                def function_struct(obj):
                    header = {'package_size': len(obj)}
                    header_json = json.dumps(header)
                    header_json_bytes = header_json.encode(self.str_code)
                    self.conn.send(struct.pack('i', len(header_json_bytes)))
                    self.conn.send(header_json_bytes)
                    self.conn.send(obj.encode(self.str_code))
                try:
                    path = path.split(' ',1)
                    if cmd == 'ls':
                        user_file_path = os.path.join(self.ftps_file,user)
                        obj = os.listdir(user_file_path)
                        if obj == []:
                            obj = 'there is nothing'
                        obj = json.dumps(obj)
                        function_struct(obj)
                    elif cmd == 'cd':
                        os.chdir(path[1])
                        obj = os.getcwd()
                        print(obj)
                        function_struct(obj)
                    else:
                        obj = os.popen(cmd).read()
                        if not obj:
                            obj = 'commands is not defined'
                        function_struct(obj)
                except ConnectionResetError:
                    print('接收或执行异常')
    
        def get(self,cmd,user):
                share_file = os.path.join(self.ftps_file, cmd[1])
                header = {'filename':cmd[1],
                          'file_size':os.path.getsize(share_file),
                          'md5':info.hash_data.hexdigest()}
                header_json = json.dumps(header)
                header_json_bytes = header_json.encode(self.str_code)
                header_struct = struct.pack('i',len(header_json_bytes))
                print(header_struct)
                self.conn.send(header_struct)
                self.conn.send(header_json_bytes)
                data_len = header['file_size']
                send_size = 0
                with open(share_file,'rb')as f:
                    for i in f:
                        self.conn.send(i)
                        send_size += len(i)
    
        def put(self,cmd,user,head_dic):   #user为登录的用户名    cmd为操作命令list,[0]为操作,[1]为操作信息
            share_file = os.path.join(self.ftps_file,user,cmd[1])
            # header_struct = self.conn.recv(4)
            # header_len = struct.unpack('i',header_struct)[0]
            # header_json = self.conn.recv(header_len).decode(self.str_code)
            # header_dic = json.loads(header_json)
            recv_size = 0
            total_size = head_dic['file_size']
            with open(share_file, 'wb')as f:
                while recv_size < total_size:
                    recv_data = self.conn.recv(self.package_size_tra)
                    f.write(recv_data)
                    recv_size += len(recv_data)
                else:
                    print('receive file complete')
                return
    
        def summary(self):
            while True:
                print('wait line')
                self.conn,self.addr_ip = self.wait_line() # 这个位置后面的代码里添加线程池
                print(self.addr_ip)
                while True:
                    self.conn.send('输入用户名:'.encode(self.str_code))
                    user = self.conn.recv(self.package_size_tra)
                    if not user:continue
                    user = user.decode(self.str_code)
                    self.conn.send('输入密码:'.encode(self.str_code))
                    password = self.conn.recv(self.package_size_tra)
                    if not password:continue
                    password = password.decode(self.str_code)
                    # 生成用户账号、密码
                    user_pass = (user,password)
                    flag = authentication(user_pass)
                    # 认证信息是否成功
                    if flag == False:
                        self.conn.send('authentication is false'.encode(self.str_code))
                        continue
                    else:
                        self.conn.send('ok'.encode(self.str_code))
                        user_file_path = os.path.join(self.ftps_file,user)
    
                        if not os.path.exists(user_file_path):
                            os.mkdir(user_file_path)
    
                        while True:
                            data = self.conn.recv(self.package_size_tra)
                            if not data:continue
                            datas = data.decode(self.str_code)
                            cmd = datas.split()
                            if cmd[0] == 'get':
                                if not os.path.exists(os.path.join(self.ftps_file,cmd[1])):
                                    continue
                                self.get(cmd,user)
                            elif cmd[0] == 'put':
                                header_struct = self.conn.recv(4)
                                header_len = struct.unpack('i', header_struct)[0]
                                header_json = self.conn.recv(header_len).decode(self.str_code)
                                header_dic = json.loads(header_json)
                                file_data_size = 0
                                if header_dic['file_size'] > info.total_package[user]:
                                    self.conn.send('file is too bigger'.encode(self.str_code))
                                    continue
                                if os.listdir(user_file_path) == []:
                                    self.conn.send('ok'.encode(self.str_code))
                                    self.put(cmd, user, header_dic)
                                    continue
                                for i in os.listdir(user_file_path):
                                    file_data_size += os.path.getsize(os.path.join(user_file_path,i))
                                if file_data_size < info.total_package[user]:
                                    if info.total_package[user] - file_data_size > header_dic['file_size']:
                                        self.conn.send('ok'.encode(self.str_code))
                                        self.put(cmd,user,header_dic)
                                    else:
                                        self.conn.send('file is too bigger'.encode(self.str_code))
                                    continue
                            else:
                                self.run_commands(cmd[0],user,datas)
                            continue
    server_core main.py
    # author:nie cheng ping
    from  client.core.main import FTPclient
    from  client.conf_c import info_c
    import sys
    base_dir = info_c.base_dir
    sys.path.insert(0,base_dir)
    
    
    if __name__ == '__main__':
        ftp_client = FTPclient(('127.0.0.1',8081))
        ftp_client.summary()   # 汇总程序功能!测试通过后设置端口ip复用
    client_bin start.py
    #author:nie cheng ping
    # _*_ coding=gbk _*_
    import os
    import socket
    import string
    import hashlib
    import random
    
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    user_file_dir = 'file_position'
    coding = 'gbk'
    
    md5_data = ''.join(random.sample(string.digits,6))
    hash_data = hashlib.md5()
    hash_data.update(md5_data.encode(coding))
    
    file_path_c = os.path.join(base_dir,user_file_dir)
    package_size = 2048
    socket_net = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    
    commands_list = ['run_commands','get','put']
    client_conf_c info_c.py
    #author:nie cheng ping
    # _*_ coding=gbk _*_
    import os
    import socket
    import string
    import hashlib
    import random
    
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    user_file_dir = 'file_position'
    coding = 'gbk'
    
    md5_data = ''.join(random.sample(string.digits,6))
    hash_data = hashlib.md5()
    hash_data.update(md5_data.encode(coding))
    
    file_path_c = os.path.join(base_dir,user_file_dir)
    package_size = 2048
    socket_net = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    
    commands_list = ['run_commands','get','put']
    client_core main.py

    哎,没什么文采,就这么将就一下了,上班忙,慢慢改进吧。

  • 相关阅读:
    Netty入门
    个人网站一步一步搭建——(20)成功在本地IIS运行
    个人网站一步一步搭建——(19)开始为博客园页面绑定数据
    不得了的try catch
    个人网站一步一步搭建——(18)后台整合
    sql拆分列 时间拆分 日、月、年
    个人网站一步一步搭建——(17)简历模块
    个人网站一步一步搭建——(16)发布动态
    MVC将Base64 保存为图片
    JS图片多个上传,并压缩为Base64
  • 原文地址:https://www.cnblogs.com/encp/p/8269484.html
Copyright © 2011-2022 走看看