今日主要内容:

一 .缓冲区

二.两种黏包现象

三.黏包现象的两种解决方案

四.打印进度条(补充的,了解即可)

1. 缓冲区

缓冲区的作用 : 将程序和网络解耦(这样做的好处是程序不会以为网速的快慢而影响程序的发送)

缓冲区分为输入缓冲区和输出缓冲区(在客户端和服务端都存在缓冲区)

import subprocess
sub_obj=subprocess.Popen(
'你输入的指令', # 这里放的是你输入的指令
shell=True, # 固定格式
stdout=subprocess.PIPE, # 正确结果的存放位置
stderr=subprocess.PIPE # 错误结果的存放位置
  )

2.两种黏包现象

  1) 两个连续小包传输,因为网速过快的缘故可能会被优化算法给组合到一起进行发送

  2) 两个数据比较大的包(比如2个2000B的)传输,接收端一次性接收数据的大小 小于包的大小(比如一次性接收最大1024B),这样就会导致剩下的数据(976B)会在下一次开头接收,导致下一次的数据结果混乱.

3. 黏包现象的两种解决方案

方案1: 由于双方不知道发送的数据的大小长度,才导致黏包现象,因此我们要在发送真实数据之前,先把发送数据的具体长度发送给对方,接收端可以根据接收到的数据长度来接收下面的真实数据(这样会比较麻烦,因为在每次发送数据之前都要发送具体的数据长度,多了一个交互确认的功能).

方案1:

首先我们看一下服务端的具体代码:

# 黏包现象解决方案1 服务端
import socket
import subprocess
sever=socket.socket()
ip_port=('127.0.0.1',8008)
sever.bind(ip_port)
sever.listen()
conn,addr=sever.accept()
while 1:
from_client_msg=conn.recv(1024)
print(from_client_msg.decode('utf-8'))
#接收到客户端发来的指令后,服务端先通过subprocess模块找到服务端系统,然后执行这个命令
sub_obj=subprocess.Popen(
from_client_msg.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
#从管道中拿到sudout正确的结果,通过Popen实例化对象,read()获取结果
std_msg=sub_obj.stdout.read()
#为了解决黏包的现象,我们先统计消息的长度,先发送消息的长度,在发送真实的数据
std_len_msg=len(std_msg)
#转化成字节长度
std_len_bytes=bytes(str(std_len_msg)).encode('utf-8')
# 看一下长度
print('指令执行结果长度>>>>>',std_len_msg)
conn.send(std_len_bytes)
#接收数据
msg=conn.recv(1024)
# 发送真实数据
conn.send(std_msg)

  

下面我们来看一下客户端的代码

import socket
client=socket.socket()
ip_port=('127.0.0.1',8008)
client.connect(ip_port)
while 1:
to_msg=input('请输入你的指令:')
# 向服务端发送你的指令
client.send(to_msg.encode('utf-8'))
# 服务端第一次发送的是数据的长度(长度是bytes类型)
from_sever_len=client.recv(1024).decode('utf-8')
# 客户端接收数据按照服务端给的长度来接收
client_result=client.recv(int(from_sever_len))
print(client.result.decode('gbk'))

  

到这里解决黏包现象的第一种方案已经写完了,下面要介绍第二种解决黏包现象的方案  

方案2:

这里的方案2需要用到的是struct模块

import struct

打包: struct.pack('i',长度)

解包: struct.unpack('i',字节)

老样子,服务端的代码

import socket
import subprocess
import struct
sever=socket.socket()
ip_port=('127.0.0.1',8008)
sever.bind(ip_port)
sever.listen()
conn,addr=sever.accept()
while 1:
from_client_msg=conn.crev(1024)
print(from_client_msg.decode('utf-8'))
# 和第一种一样,接收客户端的指令,先在服务端通过subprocess模块到系统里执行
sub_obj=subprocess.Popen(
from_client_msg.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
#从管道中拿到正确的stdout,通过read()方法或取管道中的结果
sub_result=sub_obj.sudout.read()
#为了解决黏包现象,我们先统计数据的长度,现将长度发送给客户端,
  客户端通过长度来接受我们后面要发送的真实的数据.
sub_obj_len=len(sub_result)
# 打印一下长度
print('指令的执行结果长度',sub_obj_len)
#以下数据就是跟第一种方法的区别
msg_lenint=struct.pack('i',sub_obj_len)
# 将长度和数据一起发送出去(拼接)
conn.send(msg_lenint+sub_result)

  

下面是客户端的代码

import socket
import struct
client=socket.socket()
ip_port=('127.0.0.1',8008)
client.connect(ip_port)
while 1:
client_msg=input('请输入你的指令:')
client.send(client_msg.encode('utf-8'))
#先接受4个字节,这4个字节是服务端发送的长度
from_sever_msg=client.recv(4)
#解包,解包后的结果为(xx,)元组,我们要拿到xx,直接[0]即可.此时拿到的就是数据的长度
msg_len=struct.unpack('i',from_sever_len)[0]
#拿到数据
from_client_rst=client.recv(msg_len)
#打印结果
print(from_client_rst.decode('gbk'))

  

4.打印进度条(补充的,了解即可)

import time

for i in range(20):

  print(' \r ' + " * " * i,end=' ') # \r的作用是每次打印从头开始打印

  time.sleep(3)

day28 黏包及黏包解决方案的更多相关文章

  1. Python 黏包及黏包解决方案

    粘包现象 说粘包之前,我们先说两个内容,1.缓冲区.2.windows下cmd窗口调用系统指令 1 缓冲区(下面粘包现象的图里面还有关于缓冲区的解释) 每个 socket 被创建后,都会分配两个缓冲区 ...

  2. 有关 Android Studio 重复引入包的问题和解决方案

    虽然相同包名相同类名的文件在不同 SDK 中出现的概率极低,但是一旦出现,处理起来就比较棘手.最好的解决方案就是联系提供 SDK 的技术人员反映问题,让其通过修改源码重新打包一个新的 Jar 包. 还 ...

  3. Netty中粘包和拆包的解决方案

    粘包和拆包是TCP网络编程中不可避免的,无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制. TCP粘包和拆包 TCP是个“流”协议,所谓流,就是没有界限的一串 ...

  4. java nio消息半包、粘包解决方案

    问题背景 NIO是面向缓冲区进行通信的,不是面向流的.我们都知道,既然是缓冲区,那它一定存在一个固定大小.这样一来通常会遇到两个问题: 消息粘包:当缓冲区足够大,由于网络不稳定种种原因,可能会有多条消 ...

  5. TCP 粘包 - 拆包问题及解决方案

    目录 TCP粘包拆包问题 什么是粘包 - 拆包问题 为什么存在粘包 - 拆包问题 粘包 - 拆包 演示 粘包 - 拆包 解决方案 方式一: 固定缓冲区大小 方式二: 封装请求协议 方式三: 特殊字符结 ...

  6. TCP粘"包"问题浅析及解决方案Golang代码实现

    一.粘"包"问题简介 在socket网络编程中,都是端到端通信,客户端端口+客户端IP+服务端端口+服务端IP+传输协议就组成一个可以唯一可以明确的标识一条连接.在TCP的sock ...

  7. 粘包处理现象及其解决方案——基于NewLife.Net网络库的管道式帧长粘包处理方法

    [toc] #1.粘包现象 每个TCP 长连接都有自己的socket缓存buffer,默认大小是8K,可支持手动设置.粘包是TCP长连接中最常见的现象,如下图 socket缓存中有5帧(或者说5包)心 ...

  8. day34 基于TCP和UDP的套接字方法 粘包问题 丢包问题

    TCP 基于流的协议 又叫可靠性传输协议 通过三次握手 四次挥手 来保证数据传输完毕 缺点效率低 正因为是基于流的协议 所以会出现粘包问题粘包问题:原因一:是应为数据是先发送给操作系统,在操作系统中有 ...

  9. DNS反射放大攻击分析——DNS反射放大攻击主要是利用DNS回复包比请求包大的特点,放大流量,伪造请求包的源IP地址为受害者IP,将应答包的流量引入受害的服务器

    DNS反射放大攻击分析 摘自:http://www.shaojike.com/2016/08/19/DNS%E6%94%BE%E5%A4%A7%E6%94%BB%E5%87%BB%E7%AE%80%E ...

  10. Netty - 粘包和半包(下)

    上一篇介绍了粘包和半包及其通用的解决方案,今天重点来看一下 Netty 是如何实现封装成帧(Framing)方案的. 解码核心流程 之前介绍过三种解码器FixedLengthFrameDecoder. ...

随机推荐

  1. Python Appium 开启Android测试之路

    1.获取 Android app的Activity 打开终端cmd,先cd进入到刚才下载的“新浪.apk”目录下,然后使用aapt dump badging xxx.apk命令获取包内信息.注意,启动 ...

  2. react点滴

    1.<SubSubComp {...this.props } /> 传递属性,{...props}的方式为组件传递了这两个属性,这就是JSX中的延展属性,"..."成为 ...

  3. Android DatePickerDialog 使用方法

    (一)在Android 4.0以上系统的某些手机(如本人的测试机红米Note(系统4.4.4),以及模拟器(系统4.0)),使用如下代码创建时间选择器时,页面效果如图: Calendar cal = ...

  4. java学习视频

    随着信息化的发展,IT行业变得越来火,在开发领域,Java语言在是市面上很受欢迎的编程语言,很多初学者不知道从何学起,为了找资源浪费大量时间,而我就将自己的寻找资源分享给大家,让大家能够更加便捷的学习 ...

  5. python hashable

    判断一个对象是否hashable: hash(obj) 或 obj.__hash__() ,返回 hash 值 hashable 的有: int / float / tuple / str/  obj ...

  6. 利用Xml架构生成实体访问类

    由xml生成xsd及实体类   xmldataset工具 使用VS2005工具XSD.exe(SDK/v2.0/Bin/xsd.exe)自动生成实体类: xsd /c /namespace:myCom ...

  7. 如何使用Web3.js API 在页面中进行转账

    本文介绍如何使用Web3.js API 在页面中进行转账,是我翻译的文档Web3.js 0.2x 中文版 及 区块链全栈-以太坊DAPP开发实战 中Demo的文章说明. 写在前面 阅读本文前,你应该对 ...

  8. vue+webpack热替换

    项目地址:http://pan.baidu.com/s/1i5KCXBf 今天上午和同事完成了在mac上面调试了我的框架,最后发现问题出在window系统和mac系统在表示路径的时候出现问题,在解决这 ...

  9. ubuntu下安装CAJ阅读器

    目录 1.ubuntu下wine的基本介绍 (1)wine的介绍 (2)wine的安装 (3)exe文件的安装 (4)exe程序的卸载 (6)wine的基本使用 2.CAJ阅读器的安装 (1)首先放上 ...

  10. MSMQ 概述

    MSMQ 概述 1) MSMQ概述 MSMQ 表示微软消息队列服务.MSMQ 可以工作在在线或者离线场景,并提供异步编程功能.如果客户端离线,MSMQ将会是最合适的方法,这是因为服务端不需要等待客户端 ...