网络编程基础【day09】:socket实现文件发送(六)

本节内容

1、概述

2、文件下载实现

3、MD5值校验

一、概述

  我们如何利用socket去下载一个文件,整体思路是这样的:

  1. 读取文件名
  2. 检测文件是否存在
  3. 打开文件
  4. 检测文件大小
  5. 发送文件大小给客户端
  6. 等客户确认
  7. 开始边读边发数据
  8. 发送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):
             =  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 ]
         =  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()

 ②改动地方

总结:

  1. 上传和下载都是以客户端或者服务端加载文件,然后另外一边接收再写入文件。
  2. 解决粘包问题,在接收数据大小后需要等待确认信息。
  3. 看文件能都上传和下载,应该用MD5值去校验。
  4. 创建一个无限大的文件,请用:dd if=/dev/sda1 of=文件名,比如创建test.txt,则:dd if=/dev/sda1 of=test.txt
  5. 获取一个文件的大小:os.stat(文件名).st_size

转载于:https://www.cnblogs.com/luoahong/p/9896130.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值