python3 网络文件传输

原理:

  1. 使用Socket与服务器建立TCP连接
  2. 使用open函数以二进制模式读取文件,并分割成指定大小的数据包发送
  3. 规定在传输的开始先发送文件名,传输的结尾发送停止代号

发送端:
sender.py:

FLAG='$END$'
def sendFile_TCP(FILEPATH,ADDR,BUF=1024*64):
    import socket	
    import os						
    sk = socket.socket()            #初始化套接字
    sk.connect(ADDR)                #尝试连接目标主机,如果失败会引发异常,这里为了简便没有进行异常处理
    sum = 0
    sp='\\'           
    if sp not in FILEPATH:
        sp='/'
    filename = FILEPATH.split(sp)[-1]   #分割路径字符串,获取文件名
    sk.send(filename.encode('utf-8'))   
    with open(FILEPATH,'rb') as f:
        while True:
            os.system('title 正在发送文件:{}  已发送 {} KB'.format(filename,int(sum/1024)))
            data=f.read(BUF)
            if not data:
                break
            sk.send(data)
            sum += len(data)
    sk.send(FLAG.encode())
    os.system('title FileSender')	   
	sk.close()   					   #关闭套接字
if __name__ == "__main__":
    import os
    addr = ('127.0.0.1',20020)
    while True:
        print('【拖拽文件到此处】')
        path=input()
        sendFile_TCP(path,addr)
        

注意:

  1. 读取路径之后,通过路径分隔符\(Windows系统)或/ (Linux系统)对路径字符串FILEPATH调用split函数分割并使用返回列表的最后一个(即文件名)
    也可以用现成的函数 os.path.basename(path) 来返回一个路径字符串path中的文件名,这是完全等价的
  2. f.read函数读取指定字节数的数据,如果读到了文件尾部就会返回空数据b''
    因此使用if not data来判断是否读完了文件
  3. socket发送和接收的都是二进制数据,如果是字符串应该先encode,如果是常量字符串在引号前加一个记号b,如此处的结束标志FLAG = b'$END$',这里文件名用utf-8编码是考虑到文件名可能是中文
  4. 通过os.system 调用命令行显示当前发送了多少数据,这里的时间花销比较大,如果追求最大速度可以去掉。

接收端:
recv.py

FLAG=b'$END$'
def recvFile_TCP(ADDR,BUF=1024):
    import socket
    import os
    sk=socket.socket() 
    sk.bind(ADDR)  #绑定套接字到本机的网络地址
    sk.listen(10)  #10表示最大连接数
    while True:
        client,cli_addr = sk.accept()      #接受连接请求
        filename = client.recv(BUF).decode('utf-8')
        print('正在接受来自 [{}] 的文件[{}]'.format(cli_addr,filename))
        i = 0
        while os.path.exists(filename):
            filename='{}-{}'.format(i,filename)
            i += 1
        with open(filename ,'ab') as f:
            while True:
                data=client.recv(BUF)
                if data == FLAG:
                    break
                f.write(data)
        print('已成功接收文件{}  |  文件大小 : {} KB'.format(filename,int(os.path.getsize(filename) / 1024))) 
    	client.close()

if __name__ == "__main__":
    addr=('127.0.0.1',20020)    #本机的ip地址和端口号
    recvFile_TCP(addr)

如果服务器设置了DMZ主机,(需要在外网访问)ip地址应该写局域网内的IPv4地址,例如192.168.1.100
Windows下使用命令ipconfig
Linux下使用命令ifconfig -a (基于net-tools,如果没装先apt install net-tools)
即可查看本机局域网ip

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值