zoukankan      html  css  js  c++  java
  • socket网络编程

    表示编程这条路真得好难走,后悔大学没有读信息专业啊。

    第七周的作业:

    1. 用户登陆
    2. 上传/下载文件
    3. 不同用户家目录不同
    4. 查看当前目录下文件

    刚开始没有一点思路,上网查了很多资料,还自学了FTP。吐槽一句,讲师真是太不负责了,作业要求不详细,还没有思路。

    要实现通信,需要7个层次:物理层,数据链路(mac地址),网络层(IP),传输层(有标准的数据类型, TCP/IP 三次握手四次断开, UDP),会话层(http,smtp),表示层,应用层。 传输过程中就需要做到的事情是接收和发送,在python中,这部分功能被封装在socket模块的socket类中。

    要实现文件上传和下载,肯定是需要两个端口:一个是服务器端(server),另外一个是客户端(client)。大致的交互流程如下:

    理清楚思路之后,就是开始写代码了。

    server端的代码如下:

    import socket
    import os
    import sys
    sys.path.append('..')
    from conf import setting
    com_path = setting.DATABASE
    
    def run():
        server = socket.socket()
        server.bind(('localhost',6969))
        server.listen()
    
        while True:
            print('等待客户端的连入')
            conn, addr = server.accept()
            print('收到来自%s,%s的请求'%(str(conn),str(addr)))
            data = conn.recv(1024).decode()
            server_path = '%s\%s\%s'%(com_path['path'],com_path['server'],data)
            print('当前目录下的文件有:')
            print(os.listdir(server_path))
            #检查服务器端是否已经有目录存在,要是没有的化,创建一个目录
            if os.path.isdir(server_path):
                print('该用户的目录已经存在')
            else:
                os.mkdir(server_path)
                print('成功在远程端创建%s的目录'%data)
            while True:
                try:
                    data = conn.recv(1024)
                    if len(data) == 0:
                        continue
                    else:
                        cmd, filename = data.decode().split()
                        file_path = "%s\%s.txt"%(server_path,filename)
                        print(cmd,filename)
                    if cmd == 'download':
                        print(file_path)
                        if os.path.isfile(file_path):
                            with open(file_path,'rb') as f:
                                file_size = os.stat(file_path).st_size
                                conn.send(bytes(str(file_size),encoding='utf-8'))
                                print('已经成功传送了文件大小%s'%str(file_size))
                                conn.recv(1024) #服务器端发送文件大小后,接受客户端的相应
                                for line in f:
                                    conn.send(bytes(str(line),encoding='utf-8'))
                    elif cmd == 'upload':
                        receive_file_size = conn.recv(1024).decode()
                        conn.send('准备好接收文件'.encode())
                        receive_size = 0
                        file_total_size = int(receive_file_size)
                        with open(file_path, 'wb') as f:
                            while receive_size < file_total_size:
                                data = conn.recv(1024)
                                receive_size += len(data)
                                f.write(data)
                            print('file recv done')
                            print(receive_size,file_total_size)
                    print('更新后目录下的文件有:')
                    print(os.listdir(server_path))
                except Exception:
                    print('客户端链接断开')
                    break
    
        server.close()
    

      

    client端的代码如下:

    import socket
    import sys
    sys.path.append('..')
    import os
    from conf import setting
    com_path = setting.DATABASE
    current_user = None
    
    def auth(func):
        def wrapper(*args,**kwargs):
            global current_user
            username, pwd = input('请输入您的用户名,密码:').strip().split(',')
            user_info_path = '%s\%s.txt'%(com_path['path'],com_path['user_info'])
            exist_flag = False
            not_user = False
            with open(user_info_path,'r') as f:
                while not exist_flag:
                    for line in f:
                        if line.startswith(username):
                            if line.strip().split('|')[1] == pwd:
                                print('登录成功')
                                current_user = username
                                func()
                                break
                                exist_flag = True
                                not_user = True
                            else:
                                print('密码错误')
                if not not_user:
                    print('用户不存在')
        return wrapper
    
    @auth
    def run():
        client = socket.socket()
        client.connect(('localhost',6969))
        client_path = '%s\%s\%s'%(com_path['path'],com_path['client'],current_user)
    
        client.send(current_user.encode())#将用户名发送给服务器端,看看是否有这个客户的目录
    
        while True:
            inp = input(">>:").strip()
            if len(inp) == 0:
                continue
            try:
                cmd,filename = inp.split()
                file_path = "%s\%s.txt"%(client_path,filename)
            except:
                print('输入有误,请重新输入')
                continue
            try:
                if cmd == 'download':
                    client.send(inp.encode())
                    receive_file_size = client.recv(1024).decode()
                    print('server file size',receive_file_size)
                    client.send('准备好接收文件'.encode())
                    if os.path.isdir(client_path):
                        print('该用户的目录已经存在')
                    else:
                        os.mkdir(client_path)
                        print('成功在远程端创建%s的目录'%data)
                    receive_size = 0
                    file_total_size = int(receive_file_size)
                    with open(file_path,'wb')as f:
                        data = client.recv(1024)
                        receive_size += len(data)
                        f.write(data)
                        print('file recv done')
                        print(receive_size,file_total_size)
    
                elif cmd == 'upload':
                    # try:
                    if os.path.isfile(file_path):
                        client.send(bytes(inp,encoding='utf-8'))
                        with open(file_path,'rb') as f:
                            file_size = os.stat(file_path).st_size
                            print(file_size)
                            client.send(bytes(str(file_size),encoding='utf-8'))
                            print('已经成功传送了文件大小%s'%str(file_size))
                            client.recv(1024)
                            for line in f:
                                client.send(bytes(str(line), encoding='utf-8'))
                    # except Exception:
                    #     print('只能上传文件')
            except Exception:
                break
            client.close()
    
    run()

    本来想在写一个自己的类,然后继承socket类的,但是无奈,老是出现‘OSError: [WinError 10022] 提供了一个无效的参数’错误,这个BUG我也修改不了。所以就放弃了运用面向对象的方法。希望学到以后能回过头来找出今天没有能力解决的原因吧。

  • 相关阅读:
    glBlendFunc的几种常用情况
    android发布版本的几个命令
    android拾遗——Android 动画学习笔记
    android拾遗——四大基本组件介绍与生命周期
    C++拾遗——重新开始
    mark Java NIO
    转 mysql中int、bigint、smallint 和 tinyint的区别与长度的含义
    mysql到redis的复制
    MySQL UDF(自定义函数)
    windows下redis 和 hiredis的编译与使用
  • 原文地址:https://www.cnblogs.com/little-hunter/p/6417646.html
Copyright © 2011-2022 走看看