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中的粘包,一层发送过去再进行固定长度的解包
    

      







  • 相关阅读:
    Android零碎知识之Style and Theme
    Java 线程池(一):开篇及Executor整体框架介绍
    ADB命令笔记本
    volatile变量理解 via《Java并发编程实战》
    Java NIO
    乱七八糟(一)
    Android事件分发机制
    AndroidStudio下的依赖管理
    shell--填过的坑
    兼容类问题
  • 原文地址:https://www.cnblogs.com/zhuhaofeng/p/9588474.html
Copyright © 2011-2022 走看看