粘包现象:只有tcp协议才会产生粘包,udp协议不会产生粘包

  1、tcp协议下,发送端会采用一个优化算法(Nagle算法),把间隔时间短,数据比较小的包合并到一起,再一起发送过去,造成粘包

  2、发送端从缓存区拿数据,但数据过大,只拿取一部分数据,下次再接收时,再把没有接收的数据再拿取过来,造成粘包

  对于udp协议来说,是不会发生粘包,接收端设定recvfrom多少个字节,就会接收多少个字节,超过的部分就会舍弃

拆包:当send的数据大于网卡的MTU时,数据会被分片发送,所以一般一次send的数据大小尽量不超过8k

  1. #通过tcp协议远程命令操作服务端

  2. #服务端
  3. import socket
  4. import subprocess
  5. import struct
  6.  
  7. ip_port = ("127.0.0.1", 8000)
  8. back_log = 5
  9. buffer_size = 1024
  10.  
  11. tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  12. tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  13. tcp_server.bind(ip_port)
  14. tcp_server.listen(back_log)
  15. print("--->")
  16. while True:
  17. conn, addr = tcp_server.accept( )
  18. while True:
  19. try:
  20. cmd = conn.recv(buffer_size)
  21. if not cmd:break
  22. print("来自客户端数据",cmd)
  23. res = subprocess.Popen(cmd.decode("gbk"),shell=True,
  24. stdout=subprocess.PIPE, #stdout:标准输出
  25. stdin=subprocess.PIPE, #stdin:标准输入
  26. stderr=subprocess.PIPE) #stderr:标准错误
  27. err = res.stderr.read()
  28. if err:
  29. cmd_res = err
  30. else:
  31. cmd_res = res.stdout.read()
  32. if not cmd:
  33. cmd_res = "执行成功".encode("gbk")
  34.  
  35. #解决粘包方法1
  36. # length = len(cmd_res) #计算传过来的长度
  37. # conn.send(str(length).encode("utf-8")) #将长度转换成byte,再将长度传回去
  38. # client_ready = conn.recv(buffer_size)
  39. # if client_ready == b"ready":
  40. # conn.send(cmd_res)
  41.  
  42. #解决粘包方法2
  43. length = len(cmd_res)
  44. data_length = struct.pack("i",length) #struct的pack方法直接将长度转换成byte,并且固定为4个字节
  45. conn.send(data_length)
  46. conn.send(cmd_res)
  47.  
  48. except Exception:
  49. break
  50. conn.close()
  51. tcp_server.close()
  1. #客户端
    import socket
  2. import struct
  3. from functools import partial
  4.  
  5. ip_port = ("127.0.0.1",8000)
  6. back_log = 5
  7. buffer_size = 1024
  8.  
  9. tcp_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  10. tcp_client.connect(ip_port) #链接服务端
  11.  
  12. while True:
  13. cmd = input(">>>")
  14. if not cmd:continue
  15. elif cmd == "quit":break
  16. tcp_client.send(cmd.encode("gbk"))
  17.  
  18. #解决粘包方法1
  19. # length = tcp_client.recv(buffer_size)
  20. # tcp_client.send(b"ready")
  21. # length = int(length.decode("utf-8"))
  22. # recv_size = 0
  23. # recv_msg = b""
  24. # while recv_size < length: #循环拿数据,直至数据长度超过传输回来的数据的长度
  25. # recv_msg += tcp_client.recv(buffer_size)
  26. # recv_size = len(recv_msg)
  27.  
  28. #解决粘包方法2
  29. length_data = tcp_client.recv(4) #stuctd的pack方法将长度固定为4个字节
  30. length = struct.unpack("i",length_data)[0] #stuct的unpack方法,再将长度转换回来,注意转换回来是一个元组
  31. # recv_size = 0
  32. # recv_msg = b""
  33. # while recv_size < length: #循环拿数据,直至数据长度超过传输回来的数据的长度
  34. # recv_msg += tcp_client.recv(buffer_size)
  35. # recv_size = len(recv_msg)
  36.  
  37. #用来替换循环拿取数据方法
  38. recv_msg = iter(partial(tcp_client.recv,buffer_size),b"")
  39. #partial偏移函数,第一个参数是函数,第二个参数是函数的第一个参数
  40. #iter迭代协议,第一个参数是对象,第二参数设定是对象自动迭代,直至迭代到第二个参数结束
  41. #与上面不同这个得到的是可迭代对象,需要先next()迭代数据后再decode解码
  42.  
  43. cmd_res = recv_msg
  44. print("收到服务端发来的消息:",cmd_res.__next__().decode("gbk"))
  45.  
  46. tcp_client.close()

内容补充:

  1. from functools import partial #partial偏移函数需要从functools中导入
  2. def fun(a,b):
  3. return a**b
  4. f = partial(fun,2) #使用partial有两个参数,第一个是函数,第二个是函数的第一个参数,如例:a=2
  5. print(f(3))
  6.  
  7. s = [1,2,3,4,5]
  8. def test():
  9. return s.pop()
  10. s1 = iter(test,2) #iter迭代器协议,第一个参数是迭代对象,第二个是到哪里结束
  11. for i in s1: #如例:这个对象for循环下,自动迭代到2时,迭代停止
  12. 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. JavaWEB开发03——JS

    今日任务 使用JS完成页面定时弹出广告 使用JS完成表单的校验 使用JS完成表格的隔行换色 使用JS完成复选框的全选效果 使用JS完成省市的联动效果 JS控制下拉列表左右选择 教学导航 掌握JS中的B ...

  2. 第三周syh

    第三周作业   7-1 判断上三角矩阵 (15 分) 上三角矩阵指主对角线以下的元素都为0的矩阵:主对角线为从矩阵的左上角至右下角的连线. 本题要求编写程序,判断一个给定的方阵是否上三角矩阵. 输入格 ...

  3. Vue 项目构建

    一.初始化项目 1.vue init webpack (fileName) 2.项目名称 3.项目描述 4.项目作者 5.是否依赖 .Vue 文件开发 第一个选项可以不依赖 .Vue 文件开发, 第二 ...

  4. 使用discriminator实现鉴别器

    1在人员接口实现方法 public Employee getEmpByIdStep(Integer id); 2在映射文件进行配置 <!-- public Employee getEmpById ...

  5. Hook基本知识

    一.什么是HOOK(钩子) Windows系统,建立在事件驱动机制上,就是整个系统都是通过消息传递实现的.hook(钩子)是一种特殊的消息处理机制,它可以监视系统或者进程中的各种事件消息,截获发往目标 ...

  6. 为什么在vmware中不能使用ctrl+alt+F1~6切换到字符控制台

    为什么在vmware中不能使用ctrl+alt+F1~6切换到字符控制台 是因为vmware虚拟机的快捷键: ctrl+alt也用到了 因为vmware本身的hot keys也用到了ctrl+alt: ...

  7. C#中winform下利用ArcEngine调用ArcGIS Server发布的服务 AE 10

    开发环境:vs2010 + AE 10 测试 public Form1() { ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engi ...

  8. spring boot加载自定义配置

    1.通过@Value 配置文件中 wechat: ssh: host: 192.0.1.1 port: 22 加载类 @Component @Data public class SftpConfig ...

  9. fiddler之简单的接口性能测试(replay)

    在针对某一个/某一些接口,发送相同的请求,不考虑参数的变化时,可以使用fiddler进行简单的性能测试.(使用功能为:replay) 一.replay功能调用 (1.Reissue Requests: ...

  10. 解决Pip install Pillow 失败问题

    当我在使用Django一个上传图片功能的时候, Django 提示我安装 Pillow这个图片处理的库, 当我尝试安装的时候. 总是提示安装失败 报如下错误. v = self._sslobj.rea ...