本节内容

1、概述

2、代码实现

一、概述

  上一篇博客讲到的用MD5来校验还是用的之前解决粘包的方法,就是客户端发送一个请求,等待服务端的确认的这样的一个笨方法。下面我们用另外一种方法:就是客户端已经知道可接收多少数据了,既然客户端已经知道接收多少数据了,那么客户端在接收数据的时候,正好接收已经知道的数据,不就ok了吗?就是说我循环了正好是收到已经知道的那些数据。比如:我要发5M的数据,我正好收到5M的数据,然后就不往下再收了,因为它有可能跟MD5值黏在一块了,本来说是发5M文件,结果你发了5.1M,那么客户端正好收5M的话,那客户端的0.1M是不是就不收了,不收了之后我就把客户端把文件存下来,再来recive一下,下面recive的正好是0.1M。

二、代码实现

说明:其实我们在接收文件时,只有最后一次才会超过接收大小,所以我们从这里下手

2.1、服务端代码

说明:生成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
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.send(m.hexdigest().encode())  #生成MD5值并且发送给客户端
        print("send done")
 
server.close()

②代码改动

2.2、客户端

说明:文件大小-接收大小是否大于1024 ->获取size值->recive(size)->下面再次recive时就是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
34
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:
                if file_total_size - revived_size > 1024:  #要收不止一次
                    size = 1024
                else:  #最后一次,剩多少收多少
                    size = file_total_size - revived_size
                    print("last receive:",size)
                data = client.recv(size)
                revived_size += len(data)
                m.update(data)   #计算数据接收的MD5值
                f.write(data)
            else:
                print(file_total_size,revived_size)
                new_file_md5 = m.hexdigest()  #生成接收数据的MD5值16进制形式
        server_file_md5 = client.recv(1024)  #接收客户端的MD5值
        print("server file md5:",server_file_md5.decode())
        print("client file md5:",new_file_md5)
client.close()

②代码改动

2.3、思路图

2.4、实现的效果图

网络编程基础【day09】:socket解决粘包问题之MD5(八)的更多相关文章

  1. Python网络编程基础 struct模块 解决黏包问题 FTP

    struct模块 解决黏包问题 FTP

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

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

  3. c# socket 解决粘包,半包

    处理原理: 半包:即一条消息底层分几次发送,先有个头包读取整条消息的长度,当不满足长度时,将消息临时缓存起来,直到满足长度再解码 粘包:两条完整/不完整消息粘在一起,一般是解码完上一条消息,然后再判断 ...

  4. Socket解决粘包问题1

    粘包是指发送端发送的包速度过快,到接收端那边多包并成一个包的现象,比如发送端连续10次发送1个字符'a',因为发送的速度很快,接收端可能一次就收到了10个字符'aaaaaaaaaa',这就是接收端的粘 ...

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

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

  6. python 网络编程(远程执行命令与粘包)

    远程执行命令 先来学习一个新模块 , 一会用到的.. 新模块: subprocess 执行系统命令 r = subprocess.Popen('ls',shell=True,stdout=subpro ...

  7. 【游戏开发】网络编程之浅谈TCP粘包、拆包问题及其解决方案

    引子 现如今手游开发中网络编程是必不可少的重要一环,如果使用的是TCP协议的话,那么不可避免的就会遇见TCP粘包和拆包的问题,马三觉得haifeiWu博主的 TCP 粘包问题浅析及其解决方案 这篇博客 ...

  8. Socket解决粘包问题2

    在AsynServer中对接收函数增加接收判断,如果收到客户端发送的请求信息,则发送10个测试包给发送端,否则继续接收,修改后的接收代码如下: private void AsynReceive() { ...

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

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

随机推荐

  1. BZOJ5419[Noi2018]情报中心——线段树合并+虚树+树形DP

    题目链接: [NOI2018]情报中心 题目大意:给出一棵n个节点的树,边有非负边权,并给出m条链,对于每条链有一个代价,要求选出两条有公共边的链使两条链的并的边权和-两条链的代价和最大. 花了一天的 ...

  2. Luogu5289 十二省联考2019字符串问题(后缀数组+拓扑排序+线段树/主席树/KDTree)

    先考虑80分做法,即满足A串长度均不小于B串,容易发现每个B串对应的所有A串在后缀数组上都是一段连续区间,线段树优化连边然后判环求最长链即可.场上就写了这个. 100分也没有什么本质区别,没有A串长度 ...

  3. 数据库SQL SELECT查询的工作原理

    一般开发员只会应用SQL的四条经典语句:select,insert,delete,update.但是我从来没有研究过它们的工作原理,这篇我想说一说select在数据库中的工作原理. B/S架构中最经典 ...

  4. 洛谷3822 [NOI2017] 整数 【线段树】【位运算】

    题目分析: 首先这题的询问和位(bit)有关,不难想到是用线段树维护位运算. 现在我们压32位再来看这道题. 对于一个加法操作,它的添加位置可以得到,剩下的就是做不超过32的位移.这样根据压位的理论. ...

  5. 安卓Android基础四天

    网页源码查看器 HttpURLConnection:用于发送和接受数据 ScrollView只能由一个孩子 消息机制的写法(***) anr Application not response 应用无响 ...

  6. Django+Xadmin打造在线教育系统(五)

    课程相关功能实现 课程列表 创建课程相关的urls.py path("course/", include('course.urls', namespace="course ...

  7. 使用gradle命令代替CUBA Studio,启动项目

    在cuba platform开发中,一开始都会使用CUBA Studio,这是一个脚手架,可以很方便的创建数据表.视图.Bean等.但是有时也会有奇怪的问题,比如不能读取本地maven 仓库,只读取远 ...

  8. 自学华为IoT物联网_11 物联网操作系统介绍

    点击返回自学华为IoT物流网 自学华为IoT物联网_11 物联网操作系统介绍 1.1  物联网面临的困难 物联网终端发展面临的困难:开发者需要懂硬件和芯片的差异,自行适配硬件接口 物联网开发面临的困难 ...

  9. ACM-ICPC 2018 焦作赛区网络预赛 G. Give Candies (打表找规律+快速幂)

    题目链接:https://nanti.jisuanke.com/t/31716 题目大意:有n个孩子和n个糖果,现在让n个孩子排成一列,一个一个发糖果,每个孩子随机挑选x个糖果给他,x>=1,直 ...

  10. QML-关于Qt.rgba()颜色无法正常显示问题

    GitHub:八至 作者:狐狸家的鱼 本文链接:关于Qt.rgba()颜色的正确写法 当在正常给color属性写颜色的时候,用十六进制能正常显示,但是用Qt.rgba()时,颜色无法正常显示出来. 按 ...