一、什么是TCP粘包

  C/S架构下,接收方不知道每个消息的发送间隙、也不知道每次应该提取多少个字节的数据,与此同时,TCP是面向连接的,面向流的,收发两端都要有,因此发送端为了将多个发往接收端的数据包更高效的发给对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个发送给接收端。此时接收端无法分辨出来,必须提供合理的拆包机制,即面向流的通信是无消息保护边界的。
  除此之外,因为TCP是基于流的,所以收发的消息不能为空,需要发送、接收端添加空消息处理机制,防止程序卡住。

二、处理思路

   粘包现象主要是因为发送端没有确切的发送间隔以及发送数据包的大小,而接收端更不知道发送算发送了多少个数据包以及大小,只能来多少接收多少。
   解决方法:
    自定义报头,发送端发送数据之前,先将自定义的报头(数据包大小等信息)发送给接收端,接收端明确每个数据包的大小进行依次接收。

三、实现方式

方法一:

 # 客户端
import socket
import struct IP = '127.0.0.1'
PORT = 8080
bufsize = 1024 client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client_socket.connect((IP,PORT)) while True:
cmd = input('cmd>>>').strip()
if len(cmd) == 0:continue
elif cmd == 'q':break client_socket.send(cmd.encode('utf-8')) # 1.接收固定报头
header = client_socket.recv(4) # 2.解析报头
total_size = struct.unpack('i',header)[0]
print(total_size) # 3.根据包头接收真实数据
recv_size = 0
# 保存接收的数据(接收到的是byte类型)
res_data = b''
while recv_size < total_size:
recv_data = client_socket.recv(1024)
res_data += recv_data
recv_size += len(recv_data) print(recv_data.decode('gbk')) client_socket.close() # 服务端
import socket
import subprocess
import struct IP = '127.0.0.1'
PORT = 8080
bufsize = 1024 tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_socket.bind((IP,PORT),)
tcp_socket.listen(5) while True:
conn,addr = tcp_socket.accept()
print('客户端:',addr) while True:
try:
cmd = conn.recv(bufsize)
res = subprocess.Popen(cmd.decode('utf-8'),shell=True
,stdin=subprocess.PIPE
,stdout=subprocess.PIPE
,stderr=subprocess.PIPE)
stderr = res.stderr.read()
stdout = res.stdout.read() # 1.制作固定长度的报头
total_size = len(stdout) + len(stderr)
header = struct.pack('i',total_size) # 2.发送报头
conn.send(header) # 3.发送真实数据
conn.send(stderr)
conn.send(stdout)
except ConnectionResetError:
break
conn.close()
tcp_socket.close()

解决粘包问题

方法二:

 # 客户端
import socket
import struct
import json IP = '127.0.0.1'
PORT = 8080
bufsize = 1024 client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client_socket.connect((IP,PORT)) while True:
cmd = input('cmd>>>').strip()
if len(cmd) == 0:continue
elif cmd == 'q':break client_socket.send(cmd.encode('utf-8')) # 1.接收包头长度
header_size = struct.unpack('i',client_socket.recv(4))[0] # 2.接收报头
header_bytes = client_socket.recv(header_size) # 3.解析报头
header_json = header_bytes.decode('utf-8')
header_dic = json.loads(header_json)
# print(header_dic) total_size = header_dic['total_size'] # 3.根据包头接收真实数据
recv_size = 0
# 保存接收的数据(接收到的是byte类型)
res_data = b''
while recv_size < total_size:
recv_data = client_socket.recv(1024)
res_data += recv_data
recv_size += len(recv_data) print(recv_data.decode('gbk')) client_socket.close() # 服务端
import socket
import subprocess
import struct
import json IP = '127.0.0.1'
PORT = 8080
bufsize = 1024 tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_socket.bind((IP,PORT),)
tcp_socket.listen(5) while True:
conn,addr = tcp_socket.accept()
print('客户端:',addr) while True:
try:
cmd = conn.recv(bufsize)
res = subprocess.Popen(cmd.decode('utf-8'),shell=True
,stdin=subprocess.PIPE
,stdout=subprocess.PIPE
,stderr=subprocess.PIPE)
stderr = res.stderr.read()
stdout = res.stdout.read() # 1.制作固定长度的报头
header_dic = {
'total_size':len(stdout) + len(stderr),
'md5':'123sssss222',
'filename':'120.txt'} header_json = json.dumps(header_dic)
header_bytes = header_json.encode('utf-8') # 2.发送报头的长度
total_size = len(header_bytes)
conn.send(struct.pack('i',total_size)) # 发送报头
conn.send(header_bytes) # 3.发送真实数据
conn.send(stderr)
conn.send(stdout)
except ConnectionResetError:
break
conn.close()
tcp_socket.close()

解决粘包问题

Python全栈-网络编程-TCP粘包的更多相关文章

  1. Python之路 - 网络编程之粘包

    Python之路 - 网络编程之粘包 粘包

  2. Python全栈-网络编程基础

    一.C/S架构 1.硬件C/S架构 如PC-打印机 2.软件C/S架构 如PC-网站服务器 参照: https://baike.baidu.com/item/Client%2FServer/15044 ...

  3. python套接字解决tcp粘包问题

    python套接字解决tcp粘包问题 目录 什么是粘包 演示粘包现象 解决粘包 实际应用 什么是粘包 首先只有tcp有粘包现象,udp没有粘包 socket收发消息的原理 发送端可以是一K一K地发送数 ...

  4. 8-2udp和tcp网络编程以及粘包和解决粘包的方法

    一  tcp网络编程 server 端 import socket sk=socket.socket() #实例化一个对象 sk.setsockopt(socket.SOL_SOCKET,socket ...

  5. python语法基础-网络编程-TCP协议和UDP协议

    ###############    网络编程    ############## """ 网络编程 学习了Python基础之后,包括函数,面向对象等,你就可以开发了,你 ...

  6. socket编程 TCP 粘包和半包 的问题及解决办法

    一般在socket处理大数据量传输的时候会产生粘包和半包问题,有的时候tcp为了提高效率会缓冲N个包后再一起发出去,这个与缓存和网络有关系. 粘包 为x.5个包 半包 为0.5个包 由于网络原因 一次 ...

  7. python socket网络编程之粘包问题详解

    一,粘包问题详情 1,只有TCP有粘包现象,UDP永远不会粘包 你的程序实际上无权直接操作网卡的,你操作网卡都是通过操作系统给用户程序暴露出来的接口,那每次你的程序要给远程发数据时,其实是先把数据从用 ...

  8. Python网络编程,粘包、分包问题的解决

    tcp编程中的粘包.分包问题的解决: 参考:https://blog.csdn.net/yannanxiu/article/details/52096465 服务端: #!/bin/env pytho ...

  9. python网络编程之粘包

    一.什么是粘包 须知:只有TCP有粘包现象,UDP永远不会粘包 粘包不一定会发生 如果发生了:1.可能是在客户端已经粘了 2.客户端没有粘,可能是在服务端粘了 首先需要掌握一个socket收发消息的原 ...

随机推荐

  1. [administrator][driver] driverctl 是如何在udev上层管理设备驱动的

    https://gitlab.com/driverctl/driverctl driverctl 处于 kernel 与 udev做设备与驱动管理的上层. 理解什么叫override是本文的核心内容. ...

  2. [potatos][flex][TBC] 语义分析词法分析 flex

    FLEX: The Fast Lexical Analyzer https://github.com/westes/flex 这并不是我的人生中第一次遇见flex,好多工程中,我都发现他们用到了fle ...

  3. 转:JAVA中解决Filter过滤掉css,js,图片文件等问题

    原文链接:https://www.cnblogs.com/ermeng/p/6440966.html public void doFilter(ServletRequest request, Serv ...

  4. mongodb和spring的整合

    所需jar包 mongodb.xml文件代码

  5. tomcat停止和启动脚本

    日常重启tomcat比较麻烦,所以写了2个脚本,在脚本后输入tomcat名称即可 启动或重启tomcat #!/bin/sh TOMCAT_HOME=/usr/java/$1 if [ ! -n &q ...

  6. python中由于中文路径引起的os.path.isfile(imgpath) == False问题

    昨天在用python脚本处理文件的时候,遇到了题述问题,明明文件时存在的,但是在用os.path.isfile(imgpath) == False进行判断的时候总是成立,在一开始以为是正反斜杠wind ...

  7. 王者荣耀里拿个王者有啥了不起,有胆就来挑战一下ApsaraCache源码

    王者荣耀大家估计都玩的很溜吧,撸完代码开一局,只要不遇到个猪队友,拿个鲁班后羿估计你们都能爆掉对手的塔吧.大神们打个排位赛拿个王者就和吃饭夹菜一样简单... But...你们玩过Redis和Memca ...

  8. 封装 vue 组件的过程

    首先,组件可以提升整个项目的开发效率.能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发的缺点:效率低,难维护,复用性等问题: 然后,使用Vue.extend方法创建一个组件,然后使用 Vue ...

  9. Python-多线程.md

    # 环境 - xubuntu 16.04 - anaconda - pycharm - python3.6 - https://www.cnblogs.com/jokerbj/p/7460260.ht ...

  10. RN-android 打包后,部分图片不显示

    安卓打包后以及真机调试的时候部分图片不显示,原因是 安卓的包文件并不会每次都把图片资源重新打包.也就是说,你第一次打完包之后,再更新图片与代码,代码是会生效,但是图片文件是拿不到的,解决办法是 ../ ...