本节内容

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

网络编程基础【day09】:socket实现文件发送(六)的更多相关文章

  1. 从零开始学Python第八周:网络编程基础(socket)

    Socket网络编程 一,Socket编程 (1)Socket方法介绍 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示"打开了一个网络链接",而打开一个Soc ...

  2. 网络编程基础之Socket套接字

    一.Socket介绍 1.什么是socket? Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族 ...

  3. 第1章 网络编程基础(2)——Socket编程原理

    Socket编程原理 Socket是网络通信端点的一种抽象,它提供了一种发送和接收数据的机制. 流socket(SOCK_STREAM):双向.有序.无重复.并且无记录边界 数据报Socket(SOC ...

  4. 网络编程基础之Socket套接字简单应用

    一.Socket套接字实现通信循环 所谓通信循环,简单理解就是客户端可以给服务端循环发送信息并获得反馈的过程. 1.基础版 通信循环的程序分为两部分,即两个python模块,分别为客户端.py和服务端 ...

  5. 网络编程基础之socket套接字编程实现同一IP下的信息传输

    鲁照山 1.网络协议的5层模型,每层内容的整理 2.画图描述三次握手四次挥手,和C端S端的状态 3.写一个客户端,实现给服务端发送hello world 字符串, 写一个服务端,将客户端发送的数据变成 ...

  6. 网络编程 基础 基于socket的tcp和udp连接

    网络开发的框架 C/S B/S 架构 程序都是bs架构的程序(b指浏览器,s指服务器) c(client)是客户端,s(server)是服务器 bs架构是cs架构的一种 未来的趋势, pc端bs架构, ...

  7. python网络编程基础之socket粘包现象

    粘包现象两种 登陆 #服务端import json import socket server=socket.socket()#创建socket对象 ip_port=('127.0.0.1',8001) ...

  8. 网络编程基础之TCP编程学习(一)

    网络编程基础了解 socket套接字 socket是一种通讯机制,它包含一整套的调用接口和数据结构的定义,他给应用程序提供了使用如TCP/UDP等网络通讯的手段. linux中的网络编程通过socke ...

  9. python全栈开发从入门到放弃之socket网络编程基础

    网络编程基础 一 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务 ...

  10. Linux高并发网络编程开发——10-Linux系统编程-第10天(网络编程基础-socket)

    在学习Linux高并发网络编程开发总结了笔记,并分享出来.有问题请及时联系博主:Alliswell_WP,转载请注明出处. 10-Linux系统编程-第10天(网络编程基础-socket) 在学习Li ...

随机推荐

  1. linux拷贝多个目录下的文件到同一个目录

    拷贝a目录下的a.txt和b目录下的b.txt到c目录 cp -a \ /root/a/a.txt \ /root/b/b.txt \ /root/c/

  2. 1、linux下对绝对路径和相对路径

    cd /  回到根目录         cd  /etc 回到根目录下的etc 目录下  绝对路径  路径写法是从根目录/ 写起来的. cd . 当前目录 cd .. 上层目录 cd ~回到自家的根目 ...

  3. LVS负载均衡群集

    概述 群集的类型:无论是哪种服务器,都至少包括两台节点服务器,而对外表现为一个整体,只提供一个访问入口(域名或IP地址),相当于一台大型计算机.根据群集所针对的目标差异,可以分为以下三个类型: 1.负 ...

  4. nginx-添加禁止访问规则

    location ~* /application/(admin|index)/static/.*$ { allow all; } location ~* /(applicaion|addos|coe| ...

  5. python 模块之-json

    python 模块json import json x="[null,true,false,1]" print(json.loads(x))   #---------------- ...

  6. Redis——Linux(centos7.x)下Redi和PHP Redis插件安装——【一】

    Redis 安装 下载地址:http://redis.io/download,下载最新文档版本. $ wget http://download.redis.io/releases/redis-4.0. ...

  7. P1035 调和级数

    两种解法如下: 1.模拟 这种做法的思路是枚举n从1开始,直到Sn>k结束,只需要一个循环即可实现. 代码: #include<cstdio> int main() { ; scan ...

  8. 实验九 在JSP中使用数据库

    实验性质:验证性 实验学时: 1学时 实验地点: 一 .实验目的与要求 1. 掌握在JSP中使用数据库的方法. 2. 掌握JSP对数据库的基本操作:增.删.改.查. 二. 实验内容 1.JSP访问数据 ...

  9. python主流测试框架的简介

    1.python自动化的一些测试框架 1).unitest(也称为PyUnit)  地址:https://docs.python.org/2/library/unittest.html 2).Nose ...

  10. 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT

    题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...