解决tcp粘包
粘包现象:只有tcp协议才会产生粘包,udp协议不会产生粘包
1、tcp协议下,发送端会采用一个优化算法(Nagle算法),把间隔时间短,数据比较小的包合并到一起,再一起发送过去,造成粘包
2、发送端从缓存区拿数据,但数据过大,只拿取一部分数据,下次再接收时,再把没有接收的数据再拿取过来,造成粘包
对于udp协议来说,是不会发生粘包,接收端设定recvfrom多少个字节,就会接收多少个字节,超过的部分就会舍弃
拆包:当send的数据大于网卡的MTU时,数据会被分片发送,所以一般一次send的数据大小尽量不超过8k
#通过tcp协议远程命令操作服务端
#服务端
import socket
import subprocess
import struct ip_port = ("127.0.0.1", 8000)
back_log = 5
buffer_size = 1024 tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcp_server.bind(ip_port)
tcp_server.listen(back_log)
print("--->")
while True:
conn, addr = tcp_server.accept( )
while True:
try:
cmd = conn.recv(buffer_size)
if not cmd:break
print("来自客户端数据",cmd)
res = subprocess.Popen(cmd.decode("gbk"),shell=True,
stdout=subprocess.PIPE, #stdout:标准输出
stdin=subprocess.PIPE, #stdin:标准输入
stderr=subprocess.PIPE) #stderr:标准错误
err = res.stderr.read()
if err:
cmd_res = err
else:
cmd_res = res.stdout.read()
if not cmd:
cmd_res = "执行成功".encode("gbk") #解决粘包方法1
# length = len(cmd_res) #计算传过来的长度
# conn.send(str(length).encode("utf-8")) #将长度转换成byte,再将长度传回去
# client_ready = conn.recv(buffer_size)
# if client_ready == b"ready":
# conn.send(cmd_res) #解决粘包方法2
length = len(cmd_res)
data_length = struct.pack("i",length) #struct的pack方法直接将长度转换成byte,并且固定为4个字节
conn.send(data_length)
conn.send(cmd_res) except Exception:
break
conn.close()
tcp_server.close()
#客户端
import socket
import struct
from functools import partial ip_port = ("127.0.0.1",8000)
back_log = 5
buffer_size = 1024 tcp_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_client.connect(ip_port) #链接服务端 while True:
cmd = input(">>>")
if not cmd:continue
elif cmd == "quit":break
tcp_client.send(cmd.encode("gbk")) #解决粘包方法1
# length = tcp_client.recv(buffer_size)
# tcp_client.send(b"ready")
# length = int(length.decode("utf-8"))
# recv_size = 0
# recv_msg = b""
# while recv_size < length: #循环拿数据,直至数据长度超过传输回来的数据的长度
# recv_msg += tcp_client.recv(buffer_size)
# recv_size = len(recv_msg) #解决粘包方法2
length_data = tcp_client.recv(4) #stuctd的pack方法将长度固定为4个字节
length = struct.unpack("i",length_data)[0] #stuct的unpack方法,再将长度转换回来,注意转换回来是一个元组
# recv_size = 0
# recv_msg = b""
# while recv_size < length: #循环拿数据,直至数据长度超过传输回来的数据的长度
# recv_msg += tcp_client.recv(buffer_size)
# recv_size = len(recv_msg) #用来替换循环拿取数据方法
recv_msg = iter(partial(tcp_client.recv,buffer_size),b"")
#partial偏移函数,第一个参数是函数,第二个参数是函数的第一个参数
#iter迭代协议,第一个参数是对象,第二参数设定是对象自动迭代,直至迭代到第二个参数结束
#与上面不同这个得到的是可迭代对象,需要先next()迭代数据后再decode解码 cmd_res = recv_msg
print("收到服务端发来的消息:",cmd_res.__next__().decode("gbk")) tcp_client.close()
内容补充:
from functools import partial #partial偏移函数需要从functools中导入
def fun(a,b):
return a**b
f = partial(fun,2) #使用partial有两个参数,第一个是函数,第二个是函数的第一个参数,如例:a=2
print(f(3)) s = [1,2,3,4,5]
def test():
return s.pop()
s1 = iter(test,2) #iter迭代器协议,第一个参数是迭代对象,第二个是到哪里结束
for i in s1: #如例:这个对象for循环下,自动迭代到2时,迭代停止
print(i)
解决tcp粘包的更多相关文章
- python套接字解决tcp粘包问题
python套接字解决tcp粘包问题 目录 什么是粘包 演示粘包现象 解决粘包 实际应用 什么是粘包 首先只有tcp有粘包现象,udp没有粘包 socket收发消息的原理 发送端可以是一K一K地发送数 ...
- Netty使用LineBasedFrameDecoder解决TCP粘包/拆包
TCP粘包/拆包 TCP是个”流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TC ...
- 深入学习Netty(5)——Netty是如何解决TCP粘包/拆包问题的?
前言 学习Netty避免不了要去了解TCP粘包/拆包问题,熟悉各个编解码器是如何解决TCP粘包/拆包问题的,同时需要知道TCP粘包/拆包问题是怎么产生的. 在此博文前,可以先学习了解前几篇博文: 深入 ...
- netty 解决TCP粘包与拆包问题(二)
TCP以流的方式进行数据传输,上层应用协议为了对消息的区分,采用了以下几种方法. 1.消息固定长度 2.第一篇讲的回车换行符形式 3.以特殊字符作为消息结束符的形式 4.通过消息头中定义长度字段来标识 ...
- netty 解决TCP粘包与拆包问题(一)
1.什么是TCP粘包与拆包 首先TCP是一个"流"协议,犹如河中水一样连成一片,没有严格的分界线.当我们在发送数据的时候就会出现多发送与少发送问题,也就是TCP粘包与拆包.得不到我 ...
- 1. Netty解决Tcp粘包拆包
一. TCP粘包问题 实际发送的消息, 可能会被TCP拆分成很多数据包发送, 也可能把很多消息组合成一个数据包发送 粘包拆包发生的原因 (1) 应用程序一次写的字节大小超过socket发送缓冲区大小 ...
- c#解决TCP“粘包”问题
一:TCP粘包产生的原理 1,TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾.出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能 ...
- 【转】Netty之解决TCP粘包拆包(自定义协议)
1.什么是粘包/拆包 一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据.TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的消 ...
- Netty之解决TCP粘包拆包(自定义协议)
1.什么是粘包/拆包 一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据.TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的消 ...
- golang 解决 TCP 粘包问题
什么是 TCP 粘包问题以及为什么会产生 TCP 粘包,本文不加讨论.本文使用 golang 的 bufio.Scanner 来实现自定义协议解包. 协议数据包定义 本文模拟一个日志服务器,该服务器接 ...
随机推荐
- android sp文件一个键值保存多条信息
之前碰到过这样的问题,sp文件只能够append,或者清空.其实一个键值,通过,分割,或者替代可以实现多条信息的存储.下面是一个举例: package com.ctbri.weather.utils; ...
- react注
创建新项目: npm create-react-app test1 运行项目:npm start
- mysql 5.7 Could not load driverClass com.mysql.cj.jdbc.Driver
参考: http://www.manongjc.com/article/24424.html https://blog.csdn.net/kingscoming/article/details/788 ...
- python连接字符串的几种方法--转子(香草拿铁的园子)
一. str1+str2 string类型 ‘+’号连接 >>> str1="Good" >>> str2="Luck" & ...
- JPagination分页插件的使用(ASP.NET中使用)
前台代码 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.asp ...
- leetcode 234 回文链表 Palindrome Linked List
要求用O(n)时间,和O(1)空间,因此思路是用本身链表进行判断,既然考虑回文,本方法思想是先遍历一次求链表长度,然后翻转前半部分链表:然后同时对前半部分链表和后半部分链表遍历,来判断对应节点的值是否 ...
- 分布式任务队列 Celery —— 应用基础
目录 目录 前文列表 前言 Celery 的周期定时任务 Celery 的同步调用 Celery 结果储存 Celery 的监控 Celery 的调试 前文列表 分布式任务队列 Celery 分布式任 ...
- 阶段3 1.Mybatis_12.Mybatis注解开发_5 mybatis注解建立实体类属性和数据库表中列的对应关系
创建新项目,一对多 复制刚才关闭的项目的文件 复制到们的新项目里面 复制包的依赖 删减相关代码.只保留这三个查询的方法 模糊查询改成传统的占位符的方式 之前是可以自定义实体类的属性字段,和数据库的字典 ...
- LoadRunner11安装及破解
一.LoadRunner11安装 以管理员身份运行setup.exe 选择第一个LoadRunner完整安装程序 按照界面会弹出以上提示框,直接选择否 检查系统缺少哪些组件,点击“确定”自动安装 点击 ...
- Oracle不完全恢复-主动恢复和incarnation/RMAN-20208/RMAN-06004
12.3 主动恢复 主动不完全恢复是将数据库“撤回”到从前的传统方法,主要用来撤销认为修改.一般需要先判断PIT点的时间或SCN --1 重启db到mount状态 --2 用restore将所有的数据 ...