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

 

  

 

 







posted @ 2018-09-04 21:03  solomon123  阅读(158)  评论(0编辑  收藏  举报