网络编程基础【day09】:socket实现文件发送(六)
本节内容
1、概述
2、文件下载实现
3、MD5值校验
一、概述
我们如何利用socket去下载一个文件,整体思路是这样的:
- 读取文件名
- 检测文件是否存在
- 打开文件
- 检测文件大小
- 发送文件大小给客户端
- 等客户确认
- 开始边读边发数据
- 发送md5值给客户端校验
友情提示:以下代码都是在Linux系统,并且是python3换将下实验的。
二、文件下载实现
2.1、服务端代码
逻辑:获取命令和文件名->判断文件是否存在->打开文件->获取文件大小->发送文件大小给客户端->等待客户端确认->边读边发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import hashlib import socket,os server = socket.socket() server.bind(( "localhost" , 9999 )) server.listen() while True : conn,addr = server.accept() print ( "new conn:" ,addr) while True : print ( "等待新指令" ) data = conn.recv( 1024 ) if not data: print ( "客户端已断开" ) break cmd,filename = data.decode().split() #接收客户端发过来的命令和文件名 print (filename) if os.path.isfile(filename): #判断文件是否存在 # m = hashlib.md5() with open (filename, "rb" ) as f: file_size = os.stat(filename).st_size #获取文件大小 conn.send( str (file_size).encode() ) #发送文件大小 conn.recv( 1024 ) for line in f: #m.update(line) conn.send(line) #边读边发给客户端 #print("file md5",m.hexdigest()) print ( "send done" ) server.close() |
2.2、客户端代码
逻辑:判断是否是下载命令(get) ->发送下载命令和文件名 ->获取文件大小->发送确认信息->判断时候已经全部接收
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import socket client = socket.socket() client.connect(( "localhost" , 9999 )) while True : cmd = input ( ">>>:" ).strip() if len (cmd) = = 0 : continue if cmd.startswith( "get" ): client.send(cmd.encode()) #发送下载命令和文件名 server_respose = client.recv( 1024 ) #接收文件大小 print ( "server response:" ,server_respose) client.send( "ready to recv file" .encode()) #发送确认信息 file_total_size = int (server_respose.decode()) revived_size = 0 #初始化接收大小 filename = cmd.split()[ 1 ] #获取文件名 with open (filename + ".new" , "wb" ) as f: while revived_size < file_total_size: #判断接收大小和文件大小比较 data = client.recv( 1024 ) revived_size + = len (data) #接收大小 f.write(data) #写入文件 else : print (file_total_size,revived_size) print ( "file recv done" ) client.close() |
三、MD5值校验
说明:上面只提到了怎么传输,我们在概述里面也提到了最后要用MD5值做校验,但是很显然没看到,下面我们就来说说怎么用MD5值做比较
3.1、服务端
说明:生成md5的对象->计算MD5值->生成16进制的形式->编码后发送给客户端
①代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
import hashlib import socket,os server = socket.socket() server.bind(( "localhost" , 9999 )) server.listen() while True : conn,addr = server.accept() print ( "new conn:" ,addr) while True : print ( "等待新指令" ) data = conn.recv( 1024 ) if not data: print ( "客户端已断开" ) break cmd,filename = data.decode().split() print (filename) if os.path.isfile(filename): m = hashlib.md5() #生成MD5的对象 with open (filename, "rb" ) as f: file_size = os.stat(filename).st_size conn.send( str (file_size).encode() ) #send file size conn.recv( 1024 ) for line in f: m.update(line) #计算md5值 conn.send(line) print ( "file md5" ,m.hexdigest()) conn.recv( 1024 ) #等待客户确认发送MD5值 conn.send(m.hexdigest().encode()) #生成MD5值并且发送给客户端 print ( "send done" ) server.close() |
②改动的地方
3.2、客户端
说明:生成MD5值->计算接收的数据的MD5值->生成接收数据的MD5值16进制的形式->发送接收MD5值确认信息->接收客户端的MD5值->客户端和服务端的MD5值做比较
①代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
# __auther__ == zhangqigao import socket,hashlib client = socket.socket() client.connect(( "localhost" , 9999 )) while True : cmd = input ( ">>>:" ).strip() if len (cmd) = = 0 : continue if cmd.startswith( "get" ): client.send(cmd.encode()) server_respose = client.recv( 1024 ) print ( "server response:" ,server_respose) client.send( "ready to recv file" .encode()) file_total_size = int (server_respose.decode()) revived_size = 0 filename = cmd.split()[ 1 ] m = hashlib.md5() #生成MD5对象 with open (filename + ".new" , "wb" ) as f: while revived_size < file_total_size: data = client.recv( 1024 ) revived_size + = len (data) m.update(data) #计算数据接收的MD5值 f.write(data) else : print (file_total_size,revived_size) client_md5_vaule = m.hexdigest() #生成接收数据的MD5值16进制形式 client.send( "ready to recv file md5 value" .encode()) server_md5_value = client.recv( 1024 ) #接收客户端的MD5值 if client_md5_vaule = = server_md5_value.decode(): #客户端和服务端的MD5值做比较 print ( "file recv done" ) else : print (client_md5_vaule,server_md5_value.decode()) client.close() |
②改动地方
总结:
- 上传和下载都是以客户端或者服务端加载文件,然后另外一边接收再写入文件。
- 解决粘包问题,在接收数据大小后需要等待确认信息。
- 看文件能都上传和下载,应该用MD5值去校验。
- 创建一个无限大的文件,请用:dd if=/dev/sda1 of=文件名,比如创建test.txt,则:dd if=/dev/sda1 of=test.txt
- 获取一个文件的大小:os.stat(文件名).st_size
网络编程基础【day09】:socket实现文件发送(六)的更多相关文章
- 从零开始学Python第八周:网络编程基础(socket)
Socket网络编程 一,Socket编程 (1)Socket方法介绍 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示"打开了一个网络链接",而打开一个Soc ...
- 网络编程基础之Socket套接字
一.Socket介绍 1.什么是socket? Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族 ...
- 第1章 网络编程基础(2)——Socket编程原理
Socket编程原理 Socket是网络通信端点的一种抽象,它提供了一种发送和接收数据的机制. 流socket(SOCK_STREAM):双向.有序.无重复.并且无记录边界 数据报Socket(SOC ...
- 网络编程基础之Socket套接字简单应用
一.Socket套接字实现通信循环 所谓通信循环,简单理解就是客户端可以给服务端循环发送信息并获得反馈的过程. 1.基础版 通信循环的程序分为两部分,即两个python模块,分别为客户端.py和服务端 ...
- 网络编程基础之socket套接字编程实现同一IP下的信息传输
鲁照山 1.网络协议的5层模型,每层内容的整理 2.画图描述三次握手四次挥手,和C端S端的状态 3.写一个客户端,实现给服务端发送hello world 字符串, 写一个服务端,将客户端发送的数据变成 ...
- 网络编程 基础 基于socket的tcp和udp连接
网络开发的框架 C/S B/S 架构 程序都是bs架构的程序(b指浏览器,s指服务器) c(client)是客户端,s(server)是服务器 bs架构是cs架构的一种 未来的趋势, pc端bs架构, ...
- python网络编程基础之socket粘包现象
粘包现象两种 登陆 #服务端import json import socket server=socket.socket()#创建socket对象 ip_port=('127.0.0.1',8001) ...
- 网络编程基础之TCP编程学习(一)
网络编程基础了解 socket套接字 socket是一种通讯机制,它包含一整套的调用接口和数据结构的定义,他给应用程序提供了使用如TCP/UDP等网络通讯的手段. linux中的网络编程通过socke ...
- python全栈开发从入门到放弃之socket网络编程基础
网络编程基础 一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务 ...
- Linux高并发网络编程开发——10-Linux系统编程-第10天(网络编程基础-socket)
在学习Linux高并发网络编程开发总结了笔记,并分享出来.有问题请及时联系博主:Alliswell_WP,转载请注明出处. 10-Linux系统编程-第10天(网络编程基础-socket) 在学习Li ...
随机推荐
- BZOJ4321queue2——DP/递推
题目描述 n 个沙茶,被编号 1~n.排完队之后,每个沙茶希望,自己的相邻的两 人只要无一个人的编号和自己的编号相差为 1(+1 或-1)就行: 现在想知道,存在多少方案满足沙茶们如此不苛刻的条件. ...
- Python中第三方模块requests解析
一.简述 Requests HTTP Library 二.模块框架 ''' __version__ _internal_utils adapters api auth certs compat coo ...
- Django+Xadmin打造在线教育系统(一)
系统概括: 系统具有完整的用户登录注册以及找回密码功能,拥有完整个人中心. 个人中心: 修改头像,修改密码,修改邮箱,可以看到我的课程以及我的收藏.可以删除收藏,我的消息. 导航栏: 公开课,授课讲师 ...
- AtCoder Regular Contest 102 E Stop. Otherwise...
题目链接:atcoder 大意:有\(n\)个骰子,每个骰子上面有\(k\)个数,分别是\(1\text ~ k\),现在求\(\forall i\in[2...2k]\),求出有多少种骰子点数的组合 ...
- Js点击触发Css3的动画Animations、过渡Transitions效果
关键是首先指定动画效果的CSS属性名称,然后在Js中改变这个属性 如果不使用Js触发,可以选择利用css的状态:hover,focus,active 来触发,也可以一开始就触发 下例为Js点击触发过渡 ...
- ramdom 中的 seed 的使用
实例 1 import ramdom # random.seed(10) # 未加 seed 的时候 for i in range(5): print(random.random()) # 每次输出结 ...
- 参考RPC
普遍RPC在客户端需要提供接口,如果不提供则无法进行调用.同时,因为客户端也依赖提供的接口,服务端的升级.优化所带来的更新,客户端也要及时的更新API,否则会带来影响.这样,就带来了依赖接口,常常更新 ...
- Linux 多网卡绑定bond
mode=0:负载均衡模式,增加带宽,两块网卡使用的是同一个MAC地址,所以必须配置网卡相连的交换机,这两个端口应采用聚合方式. mode=1:主备模式,一个线断了,另一条自动备援. mode=6:负 ...
- 【SFA官方翻译】Spring WebFlux和Spring Cloud进行响应式微服务开发
源码,修正一些错误: https://github.com/bigben0123/sample-spring-cloud-webflux 原创 SpringForAll社区 2018-05-18 作者 ...
- 牛客网NOIP赛前集训营-提高组(第一场)
牛客的这场比赛感觉真心不错!! 打得还是很过瘾的.水平也比较适合. T1:中位数: 题目描述 小N得到了一个非常神奇的序列A.这个序列长度为N,下标从1开始.A的一个子区间对应一个序列,可以由数对[l ...