学习笔记(14):Python网络编程并发编程-文件传输功能实现

立即学习:https://edu.csdn.net/course/play/24458/296245?utm_source=blogtoedu

1.课程目的:

       实现客户端输入下载文件的命令,然后将命令发送给服务端,服务端再执行下载文件的命令,最后将执行下载文件命令后的结果返回给客户端,客户端进行接收,这样就完成了一个简单的文件下载功能。文件的上传与下载类似,只是两个相反的过程

 

2.知识点与关键点:

1)os模块:可使用os.path.getsize(filename)来获取指定文件的大小;

2)在服务端接收的命令,使用split命令将接收的命令的字符串分割,判断第一个是‘get’还是‘put’,即判断时下载文件还是上传文件

 

3.完整代码

'''

服务端

'''

import socket
import subprocess
import json
import struct
import os
server_dir = r'C:\Users\jinlin\Desktop\python_further_study\socket编程\文件的传输(上传)\简单版本\serve'phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1',8080))
phone.listen(5)
while True:#接收客户端发送过来连接服务器请求res = phone.accept()conn,client_addr = reswhile True:try:#1接收客户端发送过来的命令resv = conn.recv(1024)#2将接收到的结果进行分割,获得命令以及文件名cmds = resv.decode('utf-8').split()#['get','a.txt']print('*'*50)#3处理命令,执行命令并且获得命令得到的结果cmd = cmds[0]filename = cmds[1]total_size = os.path.getsize(r'%s/%s'%(server_dir,filename))#获得文件的字节数大小#1)制作包含文件名和文件大小的文件头,用字典实现headers_dict = {"filename":filename,"filedata":"2020/03/09","total_size":total_size}#2)将字典先序列化成惊悚字符串,再转为bytes类型文件头headers_json = json.dumps(headers_dict)#3)获取bytes类型的长度headers_bytes = headers_json.encode('utf-8')headers_size = len(headers_bytes)#4)将bytes类型文件头长度定制为固定长度的报头header = struct.pack('i',headers_size)#5)向客户端发送报头conn.send(header)#6)向客户端发送包含文件信息的字典conn.send(headers_bytes)#7)通过二进制只读的方式打开文件,按行读取文件并且发送给客户端with open(filename,'rb') as fp:for line in fp:conn.send(line)except ConnectionResetError:breakconn.close()phone.close()

 

'''

客户端

'''

#导入模块
import socket
import struct
import json
client_dir = r'C:\Users\jinlin\Desktop\python_further_study\socket编程\文件的传输(上传)\简单版本\client'#1、设置phone套接字
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#2、连接服务器(打电话),本地地址:127.0.0.1
phone.connect(('127.0.0.1',8080))#3、向服务器发送请求send(),发送的数据不能直接发送字符串,因为要传送到物理层底层,因此需要转换成二进制的bytes类型进行发送,只需:发送的数据.encode('utf-8')即可
while True:cmd = input("请输入:")#向服务端发送下载文件的命令,get a.txt#修复客户端发送空字符串而服务器卡在接收信息处的bug,continue表示跳出本次循环,重新开始下一次的循环if not cmd:continuephone.send(cmd.encode('utf-8'))#4、接收服务器返回来的数据recv()#1)先接收由服务器返回来的报头,报头是固定长度的,因此取前面4字节的数据即为报头header = phone.recv(4)#返回的是一个对象#2)解析报头,得到bytes类型的文件头长度obj_truple = struct.unpack('i',header)#返回的是一个元组headers_bytes_size = obj_truple[0]#取元组第一个元素即为总字节数#3)接收bytes类型的文件头数据headers_bytes = phone.recv(headers_bytes_size)#4)将bytes类型的文件头数据反序列化成字典headers_json = headers_bytes.decode('utf-8')headers_dict = json.loads(headers_json)print(headers_dict)#5)从字典中取出字命令执行结果字节总长度total_size = headers_dict['total_size']filename = headers_dict['filename']#6)接收返回的数据with open(r'%s/%s'%(client_dir,filename), 'wb') as fp:recv_size = 0while recv_size < total_size:recv_line = phone.recv(1024)#接收小于1024bytes的数据fp.write(recv_line)recv_size += len(recv_line)print('文件总字节长为%s,已经下载了%s'%(total_size,recv_size))#5、关闭套接字phone
phone.close()

 

4.运行的结果:

...

客户端结果

...

请输入:get mn.png
{'filename': 'mn.png', 'filedata': '2020/03/09', 'total_size': 702935}
文件总字节长为702935,已经下载了6
文件总字节长为702935,已经下载了8
文件总字节长为702935,已经下载了237
文件总字节长为702935,已经下载了455
文件总字节长为702935,已经下载了686
文件总字节长为702935,已经下载了851
文件总字节长为702935,已经下载了946
文件总字节长为702935,已经下载了1113
文件总字节长为702935,已经下载了1339
文件总字节长为702935,已经下载了1387
文件总字节长为702935,已经下载了1847
文件总字节长为702935,已经下载了2009

.......

文件总字节长为702935,已经下载了702656
文件总字节长为702935,已经下载了702935

5.待改进

代码的可读性较差,可以通过函数以及面向对象来对其进行优化,增加其代码的可读性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257070.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NFS精简版配置方法

此实验的前提是防火墙需关闭。 1.关闭iptables /etc/init.d/iptables stop /etc/init.d/iptables status 2.关闭selinux setenforce 0 getenforce Permissive ---出现这个单词即代表selinux临时关闭&#xff0c;如需永久关闭则需修改/etc/sysconfig/selinux配置文件 …

Serializable接口中serialVersionUID字段的作用

序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联&#xff0c;该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。 如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同&…

重新认知指针

1、把指针指向的变量的数据类型称为指针的数据类型&#xff1b;而任何一个指针变量本身数据值的类型都是unsigned long int 2.、指针变量名前的符号“*”表示的是指向运算。 3、不要认为“ *p" 是指针变量&#xff0c;指针变量是p而不是*p 4、

分布式数据库 HBase

原文地址&#xff1a;http://www.oschina.net/p/hbase/ HBase 概念 HBase – Hadoop Database&#xff0c;是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统&#xff0c;利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。 HBase是Google Bigtable的开源实…

学习笔记(15):Python网络编程并发编程-进程理论

立即学习:https://edu.csdn.net/course/play/24458/296423?utm_sourceblogtoedu 1.进程&#xff1a;正在运行的一个过程或者一个任务&#xff1b; 2.进程与程序的区别&#xff1a;程序是一堆代码&#xff0c;程序运行起来就是进程了&#xff0c;一个程序运行两次&#xff0c;算…

【翻译】Designing Websites for iPhone X

让网站适配 iphone X 英文原文地址&#xff1a;https://webkit.org/blog/7929/...本文原文地址&#xff1a;https://github.com/cnsnake11/... The section below about safe area insets was updated on Oct 31, 2017 to reflect changes in the iOS 11.2 beta. 以下关于safe …

指针作为函数参数引用数组的任意元素

void swap(int *a,int*b) {*a*a^*b;*b*a^*b;*a*a^*b; } swap(data[j],data[j1]&#xff09;; int data[10]{13,55,48,13,62,45,754,0,10};以上是我遇到的问题&#xff0c;我觉得调用这个swap函数是不能这样直接把数组的某个元素直接丢给swap数据 在程序中参加数据处理的量不是指…

使用 Log4Net 记录日志

第一步&#xff1a;下载Log4Net 下载地址&#xff1a;http://logging.apache.org/log4net/download_log4net.cgi 把下载的 log4net-1.2.11-bin-newkey解压后&#xff0c;如下图所示&#xff1a; 双击bin文件夹 双击net文件夹&#xff0c;选择针对.NET FramerWork的不同版本 找…

Xcode常用快捷键

1. 文件CMD N: 新文件CMD SHIFT N: 新项目CMD O: 打开CMD S: 保存CMDOPtS&#xff1a;保存所有文件CMD SHIFT S: 另存为CMD W: 关闭窗口CMD Q :退出XcodeCMD SHIFT W: 关闭文件2. 编辑CMD [: 左缩进CMD ]: 右缩进CMDshiftF:项目中查找CMDG:查找下一个CMDshiftG:查…

学习笔记(16):Python网络编程并发编程-开启子进程的两种方式

立即学习:https://edu.csdn.net/course/play/24458/296424?utm_sourceblogtoedu #方式一&#xff1a;使用python内置模块multiprocessing下的process类 from multiprocessing import Process import time#定义进程函数 def task(name):print(%s is running&#xff01;%name)t…

ElasticSearch的API python调用

os json datetime datetime django.http HttpResponse reelasticsearch Elasticsearches Elasticsearch([])res8 es.search({:{:{:{::}}}} ) statistic():():hit res8[][]:a (%hit %hit[])a re.split(a);arow a:id row[] row[]idHttpResponse(a)转载于:https://blog.51cto…

HDU 1757 A Simple Math Problem (矩阵快速幂)

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1757 在吴神的帮助下才明白如何构造矩阵&#xff0c;还是好弱啊。 此处盗一张图 1 #include <iostream>2 #include <cstdio>3 #include <cstring>4 #include <cmath>5 #include <al…

Spring学习使用标签来标记资源(@Component、@Repository、 @Service和@Controller)和用法(包括如何jsp正在使用)...

首先&#xff0c;在xml其中新增部分标有下划线的文件&#xff0c;容器初始化的时候需要扫描包 注意&#xff1a; a. 包款扫描(下划线部分)一定要加&#xff0c;默认是不扫描整个包。与每一包之间’&#xff0c;’开。如过具有同样的父包&#xff0c;那么我们能够用父包来取…

python 判断字符串时是否是json格式方法

在实际工作中&#xff0c;有时候需要对判断字符串是否为合法的json格式 解决方法使用json.loads,这样更加符合‘Pythonic’写法 代码示例&#xff1a; Python import json def is_json(myjson):try:json_object json.loads(myjson)except ValueError, e:return Falsereturn Tr…

学习笔记(17):Python网络编程并发编程-Process对象的其他属性或方法

立即学习:https://edu.csdn.net/course/play/24458/296427?utm_sourceblogtoedu 1.pid与ppid&#xff1a;pid进程编码&#xff0c;ppid进程的父进程编码&#xff1b;os.getpid()查看正在运行的进程编码&#xff0c;os.getppid()查看正在运行进程的父进程编码 2.僵尸进程&…

用弦截法求一元三次方程的根x^3-5x^2+16x-80=0 ;带注释!

//用弦截法求一元三次方程的根x^3-5x^216x-800 #include<stdio.h>#include<math.h> float f(float x) //定义子函数f(x) x^3-5x^216x-80&#xff0c;当f(x) →0时&#xff0c;则x即为所求的实数根&#xff1b; { float y; y((x-5.0)*x16.0)*x-80.0; …

两个很有用的进程间通信函数popen,pclose

两个很有用的进程间通信函数popen,pclose 今天起的比较晚&#xff0c;然后来了也不想复习&#xff0c;还是看书学习--写代码--写博客有意思&#xff0c;不敢说有多精通&#xff0c;至少每天都在学习新知识&#xff0c;不求立刻完全消化&#xff0c;但求每天有进步。 现在就看看…

c++中指针箭头的用法

1、c中指针用箭头来引用类或者结构体的成员&#xff0c;箭头操作符“->”用来引用指针对象。这是是用于类&#xff0c;或者是结构体的指针变量用的。 如struct Point {int x,y;};Point *ptnew Point;pt->x1; 举例子说明一下&#xff1a;比如&#xff0c;我有一个对象dark…

化零为整WCF(14) - 事务(Transaction)

[索引页][源码下载] 化零为整WCF(14) - 事务(Transaction)作者&#xff1a;webabcd介绍WCF(Windows Communication Foundation) - 事务(Transaction)&#xff1a; 对契约方法使用TransactionFlowAttribute声明&#xff08;设置TransactionFlowOption参数&#xff09;&#x…