粘包现象:只有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粘包的更多相关文章

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

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

  2. Netty使用LineBasedFrameDecoder解决TCP粘包/拆包

    TCP粘包/拆包 TCP是个”流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TC ...

  3. 深入学习Netty(5)——Netty是如何解决TCP粘包/拆包问题的?

    前言 学习Netty避免不了要去了解TCP粘包/拆包问题,熟悉各个编解码器是如何解决TCP粘包/拆包问题的,同时需要知道TCP粘包/拆包问题是怎么产生的. 在此博文前,可以先学习了解前几篇博文: 深入 ...

  4. netty 解决TCP粘包与拆包问题(二)

    TCP以流的方式进行数据传输,上层应用协议为了对消息的区分,采用了以下几种方法. 1.消息固定长度 2.第一篇讲的回车换行符形式 3.以特殊字符作为消息结束符的形式 4.通过消息头中定义长度字段来标识 ...

  5. netty 解决TCP粘包与拆包问题(一)

    1.什么是TCP粘包与拆包 首先TCP是一个"流"协议,犹如河中水一样连成一片,没有严格的分界线.当我们在发送数据的时候就会出现多发送与少发送问题,也就是TCP粘包与拆包.得不到我 ...

  6. 1. Netty解决Tcp粘包拆包

    一. TCP粘包问题 实际发送的消息, 可能会被TCP拆分成很多数据包发送, 也可能把很多消息组合成一个数据包发送 粘包拆包发生的原因 (1) 应用程序一次写的字节大小超过socket发送缓冲区大小 ...

  7. c#解决TCP“粘包”问题

    一:TCP粘包产生的原理 1,TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾.出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能 ...

  8. 【转】Netty之解决TCP粘包拆包(自定义协议)

    1.什么是粘包/拆包 一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据.TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的消 ...

  9. Netty之解决TCP粘包拆包(自定义协议)

    1.什么是粘包/拆包 一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据.TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的消 ...

  10. golang 解决 TCP 粘包问题

    什么是 TCP 粘包问题以及为什么会产生 TCP 粘包,本文不加讨论.本文使用 golang 的 bufio.Scanner 来实现自定义协议解包. 协议数据包定义 本文模拟一个日志服务器,该服务器接 ...

随机推荐

  1. 冲刺周三The Third Day

    一.ThirdDay照片 二.项目分工 三.今日份燃尽图 四.项目进展 码云团队协同环境构建完毕 利用Leangoo制作任务分工及生成燃尽图 完成AES加解密部分代码 用代码实现对文件的新建.移动.复 ...

  2. 转载 用ShadowVolume画模型的影子

    阅读目录(Content) Shadow Volume 包围盒 动态生成包围盒 判断 多光源下的阴影 总结 问题 CSharpGL(48)用ShadowVolume画模型的影子 回到顶部(go to ...

  3. tensorflow源码分析——LSTMCell

    LSTMCell 是最简单的LSTMCell,源码位于:/tensorflow/contrib/rnn/python/ops/core_rnn_cell_impl.py.LSTMCell 继承了RNN ...

  4. set_option()函数

    这个函数用于设置dataframe的输出显示, import pandas as ps pd.set_option('expand_frame_repr', True) # True就是可以换行显示. ...

  5. 将html转化为canvas图片(清晰度高)的方法

    var copyDom = document.querySelector('.fenxiang1'); var width = copyDom.offsetWidth;//dom宽 var heigh ...

  6. C#学习基础

    c#的值类型存储在栈里,而引用类型的引用存储在栈里,数据存储在堆里. c#new关键字为对象分配一个引用而非存储数据. 引用类型关键字ref: For example: Int y; void mym ...

  7. docker windows下挂载目录和文件

    我们利用docker启动项目的时候不能直接修改容器中的内容,只能在  run  的时候挂载到本地目录或者文件来进行修改. 例子:(路径可以忽略斜杠和反斜杠,我这边使用windows的路径没有报错.do ...

  8. python基础:multiprocessing的使用

    不同于C++或Java的多线程,python中是使用多进程来解决多项任务并发以提高效率的问题,依靠的是充分使用多核CPU的资源.这里是介绍mulitiprocessing的官方文档:https://d ...

  9. spring(二) AOP注入

    AOP概念 l  AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 l  经典应用:事务管理.性能监视.安全检查.缓存 .日志等 l  Spring AOP使用纯Java实现,不需要专门的编译 ...

  10. HTML5——web存储 Web SQL 数据库 应用程序缓存 Web Workers 服务器发送事件 WebSocket

    web存储 比cookie更好的本地存储方式 localStorage - 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去除. sessionStorage - 用于临时保存同一窗口( ...