zoukankan      html  css  js  c++  java
  • 网络编程 --ftp01上传

    这是一个模拟的ftp上传功能,客户端输入命令之后,在客户端执行一个命令,把输入都上传到服务端在返回,前面是一个类似练习的例子

    客户端

    ***** 服务端的conn指的是客户端的sockt套接字的对象*****

    #小试牛刀
    # import socket
    # kt=socket.socket() #创建socket对象
    # info=("127.0.0.1",8800)
    # kt.connect(info)
    # while True:
    #     import subprocess
    #     res = subprocess.Popen("ipconfig",                #实例化Popen类  #并且接受的值是byte类型
    #                            shell=True,
    #                            stderr=subprocess.PIPE,
    #                            stdout=subprocess.PIPE)
    #     # print(len(res.stdout.read().decode("gbk")))  # 实例res通过stdout.read()方法读取数据
    #     # print(">>>hello")                            # 这个地方不能写print
    #     kt.send(res.stdout.read())
    
    ###########################################################################
    # use=input("用户名:")
    # pwd=input("密码:")
    # val=("%s|%s"%(use,pwd)).encode("utf8")             #把多个变量同时传过去
    
    ############################################################################
    import socket
    kt=socket.socket() #创建socket对象
    info=("127.0.0.1",8800)
    kt.connect(info)
    while True:
        import subprocess
        cmd=input(">>>请输入命令")
        res = subprocess.Popen(cmd,                #实例化Popen类  #并且接受的值是byte类型
                               shell=True,
                               stderr=subprocess.PIPE,
                               stdout=subprocess.PIPE)
        # print(len(res.stdout.read().decode("gbk")))  # 实例res通过stdout.read()方法读取数据
        # print(">>>hello")                            # 这个地方不能写print
        # out=res.stdout.read().decode("gbk")                          #写两个变量不让冲突,都在res上操作后面会出问题
        # print(len(out))
        # kt.send(res.stdout.read())
    
        out = res.stdout.read()
        err = res.stderr.read()
        print("out长度",len(out))
        print("err长度", len(err))
    
        #构建包头
        import struct
        # header_pack = struct.pack("i", len(out))   #把数据的长度打包成包头,和数据一起粘包发送过去,在服务端在解包
        #要发送的包头内容
        header_pack = struct.pack("i",len(out))      #i模式只能打包压缩整型类,打包的结果就是4个字节,可以直接发送
        #发送包头,
        kt.send(header_pack)
        #发送内容
        kt.send(out)                                 #包头和内容会作为粘包一起传过去,在对方一起解开
                                                    #时间间隔特别短,两次发的就会当成一个包发过去
    客户端

    服务端

    #小试牛刀
    # import socket
    # sock=socket.socket() #创建socket对象,后面的操作都是对这个对象进行操作
    #
    # info=("127.0.0.1",8800)
    # sock.bind(info)
    # sock.listen(5)
    # while   True:
    #     conn,addr=sock.accept() #开始阻塞
    #     # print("接收成功!")
    #     data=conn.recv(1024)             #recv的参数是固定长度
    #     print(data.decode("gbk"))
    #     print("接收成功!")
    ###########################################################################################
    #conn是谁?
    import socket
    import struct
    sock=socket.socket() #创建socket对象,后面的操作都是对这个对象进行操作
    
    info=("127.0.0.1",8800)
    sock.bind(info)
    sock.listen(5)
    while   True:
        conn,addr=sock.accept() #开始阻塞
        # print("接收成功!")
        data=conn.recv(4)             #recv的参数是固定长度
        data_length=struct.unpack("i",data)[0]     #对方传过来是4长度的字节,解包以后是数字表示的长度,默认在元组中,用索引取出
        print(data)
        print(data_length)
        print("接收成功!")
    
        recv_data_length=0
        recv_data=b""
        while recv_data_length<data_length:     #data_length的长度是对方传过来的,这个是最大的
            data=conn.recv(1024)
            recv_data_length+=len(data)
            recv_data+=data
        print(">>>>>>>%s"%type(recv_data))
        print(recv_data.decode("gbk"))
        # data_length=int(conn.recv(1024).decode("utf8"))
    服务端

    其中用到的一些知识点:

    struct模块


    subprocess模块

    下面是一个比较正式的的ftp上传的例子,客户端和服务端都有,有些知识点上面已经讲过了,
    server端
    import socket
    import struct
    sock=socket.socket() #创建socket对象,后面的操作都是对这个对象进行操作
    
    info=("127.0.0.1",8900)
    sock.bind(info)    #里面是一个元组
    sock.listen(5)
    
    while   True:
        conn,addr=sock.accept()       #开始阻塞
        # print("接收成功!")
        data=conn.recv(4)             #recv的参数是固定长度
        data_length = struct.unpack("i", data)[0]
        # print(data.decode("utf8"))
        recv_data_length = 0
        recv_data = b""
        while recv_data_length<data_length:
            data=conn.recv(1024)
            recv_data_length+=len(data)
            recv_data+=data
        print(">>>>>>>%s"%type(recv_data))
        print(recv_data.decode("utf8"))
        # data_length=int(conn.recv(1024).decode("utf8"))

    client端
    import socket
    import os
    import struct
    sock=socket.socket()
    info=("127.0.0.1",8900) 
    file_path=input(">>>请输入文件名,如不再当前目录请输入绝对路径:")
    sock.connect(info) #里面是一个元组
    #文件内容
    data=b""
    with open(file_path,mode="rb") as  f1:
        for line in f1:
            data+=line
    
    #构造包头
    head_packge=struct.pack("i",len(data))      #构造后的结果直接是4位的字节
    #发送包头
    sock.send(head_packge)
    #发送文件内容
    sock.send(data)
    
    
    # print("真实长度:",len(data))
    # print("压包后的四位字节:" ,struct.pack("i",len(data)))
    

      

    底层对粘包的启发

    底层数据报文有包头,地址,数据内容等,都是一次发送的,这个就类似python中的粘包,一层发送过去再进行固定长度的解包
    

      







  • 相关阅读:
    Linux常用命令-centos
    USACO 2006 Open, Problem. The Country Fair 动态规划
    USACO 2007 March Contest, Silver Problem 1. Cow Traffic
    USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法
    USACO 2015 February Contest, Silver Problem 3. Superbull Prim最小生成树算法
    LG-P2804 神秘数字/LG-P1196 火柴排队 归并排序, 逆序对
    数据结构 并查集
    浴谷国庆集训 对拍
    1999 NOIP 回文数
    2010 NOIP 普及组 第3题 导弹拦截
  • 原文地址:https://www.cnblogs.com/zhuhaofeng/p/9588474.html
Copyright © 2011-2022 走看看