粘包现象:

粘包1:连续的小包,会被优化机制给合并

粘包2:服务端一次性无法完全就收完客户端发送的数据,第二再次接收的时候,会接收到第一次遗留的内容

模拟一个粘包现象

服务端

import socket

server = socket.socket(type=socket.SOCK_STREAM)
ip_port = ('127.0.0.1',8080)
server.bind(ip_port) server.listen()
conn, addr = server.accept() # 粘包1:连续的小包,会被优化机制给合并
recv_mes1 = conn.recv(1024)
# 第二次拿到的就是空数据,因为客户端关闭,服务端会自动执行后续的recv,如果客户端没关闭,服务端就会在recv
# 处阻塞
recv_mes2 = conn.recv(1024) print('第一次接收',recv_mes1.decode('utf-8'))
print('第二次接收',recv_mes2.decode('utf-8')) conn.close()
server.close()

客户端

import socket

client = socket.socket(type=socket.SOCK_STREAM)

ip_port = ('127.0.0.1',8080)
client.connect(ip_port) client.send('哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈'.encode('utf-8'))
client.send('呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵'.encode('utf-8')) client.close()

代码执行结果:

客户端两次发的内容都被服务端第一个recv接收了,这即为粘包!

粘包解决方案一:

先告诉客户端,数据信息的长度,然后等客户端确认之后,再发送真实内容

代码示例:

import socket
# 服务端
# 读者可以自行创建一个txt文档,里面放的内容劲量大于1024字节,可以放一篇文章进去
with open('test.txt',mode='rb') as f:
content = f.read() data_len = len(content)
print('文章长度:',data_len)
data_len_str = str(data_len)
count = 0 server = socket.socket(type=socket.SOCK_STREAM)
ip_port = ('127.0.0.1',8080)
server.bind(ip_port)
server.listen()
conn, addr = server.accept()
print(addr,'已经连接') conn.send(data_len_str.encode('utf-8')) status = conn.recv(1024)
if status == b'ok':
while count <data_len:
send_mes = content[count:count+1024]
len_of_mes = len(send_mes)
conn.send(send_mes)
count +=len_of_mes server.close()
import socket
# 客户端
content = b''
count = 0
client = socket.socket(type=socket.SOCK_STREAM)
ip_port = ('127.0.0.1',8080)
client.connect(ip_port) data_len_str = client.recv(1024).decode('utf-8')
data_len = int(data_len_str) client.send(b'ok') while count < data_len:
recv_mes = client.recv(1024)
content +=recv_mes
count += 1024 print(content.decode('utf-8'))
client.close()

粘包解决方案二:

通过struct模块,将要发送的真实数据的长度进行打包,打包成4个字节,和真实数据一起一次性发送个客户端.客户端取出前4个字节,通过struct解包获得后面真实数据的长度,根据这个长度再进行数据的接受

代码示例:

import socket
import struct
# 服务端 server = socket.socket(type=socket.SOCK_STREAM)
ip_port = ('127.0.0.1',8080)
server.bind(ip_port)
server.listen()
conn, addr = server.accept()
print(addr,'已经连接') with open('test.txt',mode='rb') as f:
for data in f:
# data = f.readline()
data_len = len(data)
data_len_b = struct.pack('i',data_len)
conn.send(data_len_b+data) input('输入任意键结束')
server.close() ---------------------分割线------------------------
# 客户端
import socket
import struct client = socket.socket(type=socket.SOCK_STREAM)
ip_port = ('127.0.0.1',8080)
client.connect(ip_port)
content = b'' while 1:
recv_mes = client.recv(4)
data_len = struct.unpack('i',recv_mes)[0]
recv_mes = client.recv(data_len)
print(recv_mes.decode('utf-8'),end='') client.close()

tcp的粘包现象与解决方案的更多相关文章

  1. python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)

    一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...

  2. 基于tcp协议下粘包现象和解决方案,socketserver

    一.缓冲区 每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区.write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送 ...

  3. TCP的粘包现象

    看面经时,看到有面试官问TCP的粘包问题.想起来研一做购物车处理数据更新时遇到粘包问题,就总结一下吧. 1 什么是粘包现象 TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看, ...

  4. socket基于TCP(粘包现象和处理)

    目录 6socket套接字 7基于TCP协议的socket简单的网络通信 AF_UNIX AF_INET(应用最广泛的一个) 报错类型 单一 链接+循环通信 远程命令 9.tcp 实例:远程执行命令 ...

  5. Python之路(第三十一篇) 网络编程:简单的tcp套接字通信、粘包现象

    一.简单的tcp套接字通信 套接字通信的一般流程 服务端 server = socket() #创建服务器套接字 server.bind() #把地址绑定到套接字,网络地址加端口 server.lis ...

  6. 什么是粘包? socket 中造成粘包的原因是什么? 哪些情况会发生粘包现象?

    只有TCP有粘包现象,UDP永远不会粘包! 粘包:在接收数据时,一次性多接收了其它请求发送来的数据(即多包接收).如,对方第一次发送hello,第二次发送world, 在接收时,应该收两次,一次是he ...

  7. 2、粘包现象(struct模块)

    昨天我们所做的套接字是有漏洞的,它会出现粘包现象,没有发现这个问题的我们今天会进行演示.今天也会稍微讲解一下基于udp的套接字. 一.基于udp的套接字 udp是无链接的,先启动哪一端都不会报错 ud ...

  8. python3全栈开发-什么是粘包、粘包现象、如何解决粘包

    一.粘包现象 让我们基于tcp先制作一个远程执行命令的程序(1:执行错误命令 2:执行ls 3:执行ifconfig) 注意注意注意: res=subprocess.Popen(cmd.decode( ...

  9. python 网络编程之TCP传输&粘包传输

    只有TCP有粘包现象,UDP永远不会粘包. 所谓粘包问题主要还是C/S两端数据传输时 因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的 根本原因:粘包是由TCP协议本身造成的,T ...

随机推荐

  1. selenium+Headless Chrome实现不弹出浏览器自动化登录

    目前由于phantomjs已经不维护了,而新版的Chrome(59+)推出了Headless模式,对爬虫来说尤其是定时任务的爬虫截屏之类的是一大好事. 不过按照网络上的一些方法来写的话,会报下面的错误 ...

  2. jenkin服务关闭和重启

    1.关闭Jenkins http://localhost:8080/exit 2.重启Jenkies http://localhost:8080/restart 3.重新加载配置信息 http://l ...

  3. HDU 3466 Proud Merchants(背包问题,要好好理解)

    Problem Description Recently, iSea went to an ancient country. For such a long time, it was the most ...

  4. (转)通过maven,给没有pom文件的jar包生成pom文件,maven项目引入本地jar包

    文章完全转载自 : https://blog.csdn.net/qq_31289187/article/details/81117478 问题一: 经常遇到公司私服或者中央仓库没有的jar包,然后通过 ...

  5. 第二章 Java 基本语法1

    2.1关键字 1.定义:被Java语言赋予了特殊含义,用做专门用途的字符串(单词). 2.特点:关键字中所有字母都是小写字母. 3.分类: 用于定义数据类型的关键字:byte.short.int.lo ...

  6. Nginx 常用配置

    Nginx的负载均衡方式 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除. 2.weight 指定轮询几率,weight和访问比率成正比,用于后端 ...

  7. 如何利用redis来进行分布式集群系统的限流设计

    在很多高并发请求的情况下,我们经常需要对系统进行限流,而且需要对应用集群进行全局的限流,那么我们如何类实现呢. 我们可以利用redis的缓存来进行实现,并且结合mysql数据库一起,先来看一个流程图. ...

  8. 函数调用模式,this指向

    ## 函数的四种调用模式 1.函数模式    this--->window function test(){ console.log(this); } test(): 2.方法模式    thi ...

  9. 【数论】卢卡斯定理模板 洛谷P3807

    [数论]卢卡斯定理模板 洛谷P3807 >>>>题目 [题目] https://www.luogu.org/problemnew/show/P3807 [输入格式] 第一行一个 ...

  10. oracle 夸服务器、数据库查询

      create public database link 连接名 connect to 需要连接数据库名 identified by  需要连接数据库密码 USING '(DESCRIPTION = ...