1. recv 工作原理

1.能够接收来自socket缓冲区的字节数据;
2.当缓冲区没有数据可以读取时,recv会一直处于阻塞状态,知道缓冲区至少有一个字节数据可取,或者客户端关闭;
3.关闭远程端并读取所有数据后,再recv会返回字符串。

2.升级版解决粘包问题

应用层自定义协议FTP(文件传输协议).

low版:
只能是有限的数据,将总数据长度固定成4个字节作为报头,再recv。当文件数据特别大时,会报错。 升级版优点:
1. 自定制报头。 如:dic = {'filename':xxx, 'md5':f454d5asfa5, 'total_size':1024*1024*1024}
2. 解决文件数据过大问题。 把报头做成字典,字典里包含将要发送的真实数据的描述信息(大小啊之类的),然后json序列化,然后用struck将序列化后的数据长度打包成4个字节。
我们在网络上传输的所有数据 都叫做数据包,数据包里的所有数据都叫做报文,报文里面不止有你的数据,还有ip地址、mac地址、端口号等等,其实所有的报文都有报头,这个报头是协议规定的。 思路:
服务端:
1. 自定义报头,字典形式,里面存放文件信息等;
2. 然后将报头字典 ——> json类型字符串 ——> 编码成 bytes类型数据;
3. 将报头bytes类型的长度(len())——>固定成4个长度的字节,然后再send();
4. 将报头bytes类型的内容数据 send();
5. 再发送总数据,如果数据量特别大时,循环读取、发送字节。 客户端:
1. 先收报头固定长度,再struct,得到报头数据的长度;
2. 根据长度接收报头字节数据,再解码,反序列化成字典(json);
3. 从字典获取文件、数据的描述信息(如文件名、大小等),再获取真实的数据。
# 服务端
import socket
import subprocess
import struct
import json
phone = socket.socket() phone.bind(('127.0.0.1',8888))
phone.listen(5) while 1:
conn, addr = phone.accept()
print(f'与客户端{addr}连接') while 1:
try:
from_client_data = conn.recv(1024)
if from_client_data.upper() == b'Q':
print('客户端已退出!')
break
obj = subprocess.Popen(from_client_data.decode("utf-8"),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
total_data = obj.stdout.read() + obj.stderr.read()
print(len(total_data)) head_dict = {'filename':None,
'md5': 1324654645456,
'total_size': len(total_data)
} # 自定义报头,字典类型
head_str = json.dumps(head_dict) # 报头转换成json的字符串类型 head_bytes = head_str.encode('utf-8') # 报头 转换成 bytes 类型 head_len_bytes = struct.pack('i', len(head_bytes)) # 固定报头 字节数 conn.send(head_len_bytes) # 发送报头的 固定字节 conn.send(head_bytes) # 发送 报头数据 conn.send(total_data) # 发送 总数据, 可循环发送文件的数据 except ConnectionResetError:
print('与客户端连接中断!')
break
conn.close()
phone.close()
# 客户端

import socket
import struct
import json phone = socket.socket() phone.connect(('127.0.0.1', 8888)) while 1: to_server_data = input('>>>').strip().encode('utf-8')
if not to_server_data:
print('内容不能为空!')
continue
phone.send(to_server_data)
if to_server_data.upper() == b'Q':
break head_len_bytes = phone.recv(4) # 接收报头固定字节长度
head_int = struct.unpack('i', head_len_bytes)[0] # 报头长度反解成 int 长度
# print(head_int) head_bytes = phone.recv(head_int) # 接收int长度的 报头数据 head_dict = json.loads(head_bytes.decode('utf-8'))
# 将bytes类型的报头 转换成原类型(字典) # print(head_dict['total_size']) data = b''
while len(data) < head_dict['total_size']: # 小于文件的大小,循环
data = data + phone.recv(1024) print(len(data))
print(f"{data.decode('gbk')}") phone.close()

3. 基于UDP协议的socket通信

1. 基于UDP协议的socket通信无需建立管道,先开启服务端或者客户端都可以;
2. 基于UDP协议的socket通信,接收、发送一个消息都是无连接的;
3. 只有拿到对方IP地址和端口就可以通信发消息,按照顺序接收服务端消息。
# 服务端
import socket server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 9000)) while 1:
client_data = server.recvfrom(1024)
# print(client_data)
data = client_data[0].decode('utf-8')
print(f'来自客户端{client_data[1]}的消息:{data}') to_data = input('>>>').encode('utf-8')
server.sendto(to_data, client_data[1])
# 客户端
import socket client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 基于网络的UDP协议的socket while 1:
to_server_data = input('>>>:').strip()
client.sendto(to_server_data.encode('utf-8'), ('127.0.0.1', 9000)) data, addr = client.recvfrom(1024)
print(f'来自服务端{addr}的消息:{data.decode("utf-8")}')

python 31 升级版解决粘包现象的更多相关文章

  1. python之路--subprocess,粘包现象与解决办法,缓冲区

    一. subprocess 的简单用法 import subprocess sub_obj = subprocess.Popen( 'dir', #系统指令 shell=True, #固定方法 std ...

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

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

  3. python网络编程基础之socket粘包现象

    粘包现象两种 登陆 #服务端import json import socket server=socket.socket()#创建socket对象 ip_port=('127.0.0.1',8001) ...

  4. python--subprocess,粘包现象与解决办法,缓冲区

    一. subprocess 的简单用法 import subprocess sub_obj = subprocess.Popen( 'dir', #系统指令 shell=True, #固定方法 std ...

  5. python 粘包现象

    一. 粘包现象 1. 粘包现象的由来(1)TCP属于长连接,当服务端与一个客户端进行了连接以后,其他客户端需要(排队)等待.若服务端想要连接另一个客户端,必须首先断开与第一个客户端的连接. (2)缓冲 ...

  6. Day 6-3 粘包现象

    服务端: import socket import subprocess phone = socket.socket(family=socket.AF_INET, type=socket.SOCK_S ...

  7. socket基于TCP(粘包现象和处理)

    目录 6socket套接字 7基于TCP协议的socket简单的网络通信 AF_UNIX AF_INET(应用最广泛的一个) 报错类型 单一 链接+循环通信 远程命令 9.tcp 实例:远程执行命令 ...

  8. Python之网路编程之粘包现象

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

  9. python socket的应用 以及tcp中的粘包现象

    1,socket套接字 一个接口模块,在tcp/udp协议之间的传输接口,将其影藏在socket之后,用户看到的是socket让其看到的. 在tcp中当做server和client的主要模块运用 #s ...

随机推荐

  1. css 图片裁剪显示

    用object-fit:cover object-fit属性详解 object-fit:CSS 属性指定替换元素的内容应该如何适应到其使用的高度和宽度确定的框. object-fit:fill 被替换 ...

  2. Nodejs监控Apple召回计划&邮件提醒

    最近,我的MacBook Pro 2015款13寸电池膨胀了 把笔记本平放在桌面,四个脚中的前两个无法落地,笔记本盖合上之后,屏幕上会印上键盘的纹路,也就是说,笔记本C面D面变形了,已经购买超过3年, ...

  3. 统计学习方法(李航)朴素贝叶斯python实现

    朴素贝叶斯法 首先训练朴素贝叶斯模型,对应算法4.1(1),分别计算先验概率及条件概率,分别存在字典priorP和condP中(初始化函数中定义).其中,计算一个向量各元素频率的操作反复出现,定义为c ...

  4. 使用canvas来完成线性渐变和径向渐变的功能

    fillStyle的第二种使用情况就是渐变色的填充.渐变色就分为线性渐变色和径向渐变色.   线性渐变:大致分为两步 这里又会使用到canvas的两个新的函数.   第一步 : 使用一个新的函数cre ...

  5. 从国际象棋与象棋的走法差异,再趣说IT人提升能力和增收方式

    之前我写过篇博文,用象棋的思维趣说IT人的职业发展和钱途,发现象棋中的一些思维能应用到我们程序员平时的职业发展中. 当从大学毕业的程序员干个五六年以后,也达到了高级开发的水平,工作环境应该能摆脱动荡, ...

  6. C语言编程入门之--第二章编译环境搭建

    第二章 编译环境搭建 导读:C语言程序如何工作,首先需要编译链接成可执行文件,然后就可以运行在不同的环境中,这个“环境”的意思就是比如说,电脑,手机,路由器,蓝牙音箱等等智能设备中,其中编译器启到了关 ...

  7. java练习---4

    //程序员:罗元昊 2017.9.17 今天好累吖咦吖咦吖 package demo;import java.util.Scanner;public class Lk { public static ...

  8. 172. 阶乘后的零 Java解法

    https://leetcode-cn.com/problems/factorial-trailing-zeroes/ 172. 阶乘后的零 这题要完成其实要知道一个很巧妙的思想,就是阶乘里面,后面的 ...

  9. IO流4

    IO流的分类 根据处理数据类型的不同分为:字符流和字节流 根据数据流向不同分为:输入流和输出流 字符流和字节流 字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象.本质其实就是基于字 ...

  10. 快速安装k8s,版本为1.13.8

    利用rpm快速部署k8s #!/bin/bash #快速安装k8s #by love19791126 107420988@qq.com pwd=$(pwd) masteripaddr=#(ip a s ...