day31

recv工作原理

  1. 源码解释:
  2. Receive up to buffersize bytes from the socket.
  3. 接收来自socket缓冲区的字节数据,
  4. For the optional flags argument, see the Unix manual.
  5. 对于这些设置的参数,可以查看Unix手册。
  6. When no data is available, block untilatleast one byte is available or until the remote end is closed.
  7. 当缓冲区没有数据可取时,recv会一直处于阻塞状态,直到缓冲区至少有一个字节数据可取,或者远程端关闭。
  8. When the remote end is closed and all data is read, return the empty string.
  9. 关闭远程端并读取所有数据后,返回空字符串。

高大上版解决粘包方式(自定制报头)

我们要制作固定的报头

你现在有两段不固定长度的bytes类型,我们要固定的报头,所以

  • 你获取不固定报头的长度
  • 利用struct模块将不固定的长度转化成固定的字节数4个字节
  • 先发4个字节,再发报头数据,再发总数据
server
  1. import socket
  2. import subprocess
  3. import struct
  4. import json
  5. phone = socket.socket()
  6. phone.bind(("127.0.0.1",8080))
  7. phone.listen(3)
  8. while 1:
  9. conn, addr = phone.accep()
  10. print(f"{addr}客户端链接了")
  11. while 1:
  12. try:
  13. from_client_data = conn.recv(1024)
  14. obj = subprocess.Popen(from_client_data.decode("utf-8"),
  15. shell = True,
  16. stdout = subprocess.PIPE,
  17. stderr = subprocess.PIPE
  18. )
  19. data = obj.stdout.read() + obj.stderr.read()
  20. data_len = len(data)
  21. # 1、自定义报头
  22. head_dic = {
  23. "file_name": "test1",
  24. "md5": 654654654654,
  25. "total_size": data_len
  26. }
  27. # 2、json形式的报头
  28. head_dic_json = json.dumps(head_dic)
  29. # 3、bytes形式的报头
  30. head_dic_json_bytes = head_dic_json.encode("utf-8")
  31. # 4、bytes形式的报头的总字节数
  32. len_head_dic_json_bytes = len(head_dic_json_bytes)
  33. # 5、把报头的总字节数变成固定的4个字节
  34. four_head_bytes = struct.pack("i", len_head_dic_json_bytes)
  35. # 6、发送固定的4个字节
  36. conn.send(four_head_bytes)
  37. # 7、发送bytes形式的报头
  38. conn.send(head_dic_json_bytes)
  39. # 8、发送总数据
  40. conn.send(data)
  41. exctpt Exception:
  42. print(f"{addr}客户端关闭!")
  43. break
  44. conn.close()
  45. phone.close()
client
  1. import socket
  2. import struct
  3. import json
  4. phone = socket.socket()
  5. phone.connect(("127.0.0.1", 8080))
  6. while 1:
  7. data = input("请输入>>>")
  8. if not data:
  9. print("输入内容不为空!")
  10. continue
  11. phone.send(data.encode("utf-8"))
  12. if data.upper() == "Q":
  13. print("通信关闭")
  14. break
  15. # 1、获取报头的固定4个字节
  16. four_head_bytes = phone.recv(4)
  17. # 2、把固定的4个字节变成bytes形式的报头的总字节数
  18. len_head_dic_json_bytes = struct.unpack("i", four_head_bytes)[0]
  19. # 3、获取到bytes形式的报头
  20. head_dic_json_bytes = phone.recv(len_head_dic_json_bytes)
  21. # 4、获取json形式的报头
  22. head_dic_json = head_dic_json_bytes.decode("utf-8")
  23. # 5、获取报头
  24. dic = json.loads(head_dic_json)
  25. # 6、获取总数据长度
  26. data_len = dic["total_size"]
  27. # 7、定义一个空字节
  28. data_deposit = b""
  29. # 8、循环获取总数据
  30. while len(data_deposit) < data_len:
  31. data_deposit += phone.recv(1024)
  32. # 把总数据转成源数据
  33. print(data_deposit.decode("gbk"))
  34. phone.close()

基于UDP协议的socket通信

多人在服务器聊天

server

  1. import socket
  2. server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  3. server.bind(("127.0.0.1", 9000))
  4. while True:
  5. conn, addr = server.recvfrom(1024)
  6. print(f"来自{addr}的消息:{conn.decode('utf-8')}")

client

  1. import socket
  2. client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  3. while True:
  4. data = input(">>>")
  5. client.sendto(data.encode("utf-8"), ("172.0.0.1", 8080))
服务器与多人聊天

server

  1. import socket
  2. server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  3. server.bind(("127.0.0.1", 9000))
  4. while True:
  5. conn, addr = server.recvfrom(1024)
  6. print(f"来自{addr}的消息:{conn.decode('utf-8')")
  7. data = input(">>>")
  8. server.sendto(data.encode("utf-8"), addr)

client

  1. import socket
  2. client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  3. while True:
  4. data = input(">>>")
  5. client.sendto(data.encode("utf-8"), ("127.0.0.1", 9000))
  6. conn, addr = client.recvfrom(1024)
  7. print(f"来之{addr}的消息:{conn.decode('utf-8')}")

day31——recv工作原理、高大上版解决粘包方式、基于UDP协议的socket通信的更多相关文章

  1. 【python】-- Socket粘包问题 ,解决粘包的几种方法、socket文件下载,md5值检验

    上一篇随笔:“socket 接收大数据”,在win系统上能够运行,并且解决了大数据量的数据传输出现的问题,但是运行在linux系统上就会出现如下图所示的情况: 就是服务端两次发送给客户端的数据(第一次 ...

  2. 网络编程基础之粘包现象与UDP协议

    一.粘包现象原理分析 1.我们先来看几行代码,从现象来分析: 测试程序分为两部分,分别是服务端和客户端 服务端.py #!/usr/bin/env python3 #-*- coding:utf-8 ...

  3. python 31 升级版解决粘包现象

    目录 1. recv 工作原理 2.升级版解决粘包问题 3. 基于UDP协议的socket通信 1. recv 工作原理 1.能够接收来自socket缓冲区的字节数据: 2.当缓冲区没有数据可以读取时 ...

  4. Python网络编程04 /recv工作原理、展示收发问题、粘包现象

    Python网络编程04 /recv工作原理.展示收发问题.粘包现象 目录 Python网络编程04 /recv工作原理.展示收发问题.粘包现象 1. recv工作原理 2. 展示收发问题示例 发多次 ...

  5. 网络编程之模拟ssh远程执行命令、粘包问题 、解决粘包问题

    目录 模拟ssh远程执行命令 服务端 客户端 粘包问题 什么是粘包 TCP发送数据的四种情况 粘包的两种情况 解决粘包问题 struct模块 解决粘包问题 服务端 客户端 模拟ssh远程执行命令 服务 ...

  6. Python进阶----粘包,解决粘包(旗舰版)

    Python进阶----粘包,解决粘包(旗舰版) 一丶粘包 只有TCP有粘包现象,UDP永远不会粘包 什么是粘包     存在于客户端接收数据时,不能一次性收取全部缓冲区中的数据.当下一次再有数据来时 ...

  7. 一个完整的socket recv()案例,包括解决粘包、服务器主动推数据的问题

    前言: 本文是针对socket长连接(涉及到服务器主动推数据),每个包头的拼接算法和长度都不一样,具体的包头小伙伴们问自己公司的开发吧,本文只是提供思路.再啰嗦一句:recv到的包头中数字进行某种运算 ...

  8. Linux下tcp协议socket的recv函数返回时机分析(粘包)

    http://www.vckbase.com/index.php/wv/10http://blog.csdn.net/zlzlei/article/details/7689409 文章一: 当前在网络 ...

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

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

随机推荐

  1. vault 使用 中间ca 进行证书管理

    使用vault 进行pki 管理是很方便的,以前测试的都是由根证书进行证书签发,这次使用中间ca 进行签发 所以会有一个证书连 测试使用docker-compose 运行 环境准备 docker-co ...

  2. 开源项目 12 ServiceStack.OrmLite

    using ServiceStack; using ServiceStack.DataAnnotations; using ServiceStack.OrmLite; using ServiceSta ...

  3. MySQL的ROUND函数

    ROUND(X) ROUND(X,D) 返回参数X, 其值接近于最近似的整数.在有两个参数的情况下,返回 X ,其值保留到小数点后D位,而第D位的保留方式为四舍五入.若要接保留X值小数点左边的D 位, ...

  4. 龙格-库塔法解常微分方程(c++)

    用龙格库塔法计算 #include <iostream> #include<iomanip> #include <cmath> using namespace st ...

  5. 文档流&浮动&定位

    文档流指元素在文档中的位置由元素在html里的位置决定,块级元素独占一行,自上而下排列:内联元素从左到右排列脱离文档流的方式: 浮动,通过设置float属性 绝对定位,通过设置position:abs ...

  6. TICK/TIGK运维栈安装运行【上】

    TICK/TIGK运运维metrics栈包括 InfuluxDB:为时间序列数据专门定制的高性能数据存储.TSM引擎允许高速接收和数据压缩.完全go语言编写.编译成一个单一的二进制,没有外部依赖.简单 ...

  7. python练习:寒冰猴子狐狸,猫狗咬架

    python练习:寒冰猴子狐狸,猫狗咬架 一,寒冰猴子狐狸 class Person: def __init__(self, na, gen, age, fig): self.name = na se ...

  8. flask上传文件到指定路径

    flask上传文件到指定路径 项目结构如下: 首先是:视图函数uload_file.py,代码如下: #!/usr/bin/env python # -*- coding: utf-8 -*- fro ...

  9. JS高级:面向对象解析

    1 实例属性/方法 都是绑定在使用构造函数创建出来的对象p上; 最终使用的时候也是使用对象p来进行访问; function Person(name, age, doFunc) { this.name ...

  10. 转 perl DBI 总结

    https://www.cnblogs.com/homezzm/archive/2011/07/22/2113618.html ##查看已经安装的包 #!/usr/bin/perluse strict ...