Python-网络编程之粘包、UDP
粘包问题
什么是粘包问题呢?
在我们写 tcp socket编程的时候,tcp协议是一个流式的协议,服务端第一次发送的数据,客户端无法准确一次性的接收完毕,下一次发送的数据与上一次数据粘在一起。
即:
1、 无法预测对方需要接收的数据大小长度
2、 多次连续发送数据量小的,并且时间间隔短的数据 会一次性打包一起发送
TCP 协议的特性:
会将多次连续发送的数据量小的,并且时间间隔短的数据一次性发送完毕
subprocess模块
我们用subprocess 模块来演示一个粘包问题。
# 服务端
# coding=utf-8
import socket
import subprocess
server = socket.socket()
address = ("127.0.0.1",8888)
server.bind(address)
server.listen(5)
while True:
conn , addr = server.accept()
while True:
try:
cmd = conn.recv(1024).decode("utf-8")
print(cmd)
if cmd == "q":
break
obj = subprocess.Popen(
cmd,shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
res = obj.stdout.read() + obj.stderr.read()
conn.send(res)
except Exception:
break
conn.close()
# 客户端
# coding=utf-8
import socket
client = socket.socket()
address = ("127.0.0.1",8888)
client.connect(address)
while True:
cmd = input("请输入>>>")
client.send(cmd.encode("utf-8"))
if cmd == "q":
break
data = client.recv(1024)
print(data.decode("gbk"))
client.close()
终端打印结果
请输入>>>tasklist
映像名称 PID 会话名 会话# 内存使用
========================= ======== ================ =========== ============
System Idle Process 0 Services 0 24 K
System 4 Services 0 3,172 K
smss.exe 352 Services 0 1,200 K
csrss.exe 464 Services 0 6,656 K
wininit.exe 572 Services 0 5,168 K
csrss.exe 588 Console 1 77,948 K
services.exe 636 Services 0 12,288 K
lsass.exe 652 Services 0 11,164 K
lsm.exe 660 Services 0 4,664 K
winlogon.exe 744 Console 1 8,180 K
svchost.exe 812 Services 0 10,040 K
svchost.
请输入>>>dir
exe 892 Services 0 8,280 K
svchost.exe 980 Services 0 21,744 K
svchost.exe 168 Services 0 21,060 K
svchost.exe 388 Services 0 40,792 K
svchost.exe 908 Services 0 12,252 K
WUDFHost.exe 1100 Services 0 8,096 K
ZhuDongFangYu.exe 1188 Services 0 23,784 K
svchost.exe 1236 Services 0 17,532 K
wlanext.exe 1412 Services 0 5,268 K
conhost.exe 1420 Services 0 2,860 K
dwm.exe 1536 Console 1 38,436 K
explorer.exe 1588 Console 1 70,028 K
spoolsv.exe 1612 Services 0 12,204 K
svchost.exe
我们看到在输完tasklist 命令之后,再次输入其他命令,还是上次命令的结果,
那么久证明了 服务端第一次发送的数据,客户端无法准确一次性的接收完毕,下一次发送的数据与上一次数据粘在一起。我们在客户端接收的时候,接收的数据大小是1024个字节,服务器执行结果 超出了接收的大小,所以相当于把结果堆到了后面,一起发送,所以下次执行命令得不到正确的结果,那么我们需要解决这个问题就需要用到 struct 模块
struct模块
struct 模块必须先定义报头,,先发送报头,再发送真实数据
# 服务端
# coding=utf-8
import struct
import socket
import subprocess
server = socket.socket()
address = ("127.0.0.1",8888)
server.bind(address)
server.listen(5)
while True:
conn,addr = server.accept()
while True:
try:
cmd = conn.recv(1024).decode("utf-8")
print(cmd)
if cmd == "q":
break
obj = subprocess.Popen(
cmd ,shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
res = obj.stdout.read() + obj.stderr.read()
# 将执行结果计算长度用i模式打包
res_len = struct.pack("i",len(res))
# 先发送数据长度
conn.send(res_len)
# 再发送真实数据
conn.send(res)
except Exception:
break
conn.close()
# 客户端
# coding=utf-8
import socket
import struct
client = socket.socket()
address = ("127.0.0.1",8888)
client.connect(address)
while True:
cmd = input("请输入命令>>>")
client.send(cmd.encode("utf-8"))
if cmd == "q":
break
# 用struct模块接收的长度统一是4个字节,
head = client.recv(4)
# 然后用struct模块解包得到数据的真实长度,返回的是元组类型,0表示第一个元素,就是真实长度
data_len = struct.unpack("i",head)[0]
# 然后再把真实长度接收即可。
data = client.recv(data_len)
print(data.decode("gbk"))
client.close()
UDP协议编程
udp也是一种传输协议
1)不需要建立双向通道
2)不会粘包
3)客户端给服务端发送数据,不需要等待服务端返回接收成功
4)数据容易丢失,数据不安全。
TCP:就相当于与在打电话
UDP:就相当于与在发短信
简易qq聊天室
# 服务端
# coding=utf-8
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
address = ("127.0.0.1",8888)
server.bind(address)
while True:
msg,addr = server.recvfrom(1024)
print(msg.decode("utf-8"))
# 服务端往客户端发送消息
send_msg = input("服务端发送消息")
server.sendto(send_msg.encode("utf-8"),addr)
# 客户端
# coding=utf-8
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
address = ("127.0.0.1",8888)
while True:
send_msg = input("请输入信息")
client.sendto(send_msg.encode("utf-8"),address)
data = client.recv(1024)
print(data.decode("utf-8"))
Python-网络编程之粘包、UDP的更多相关文章
- Python网络编程,粘包、分包问题的解决
tcp编程中的粘包.分包问题的解决: 参考:https://blog.csdn.net/yannanxiu/article/details/52096465 服务端: #!/bin/env pytho ...
- python网络编程之粘包
一.什么是粘包 须知:只有TCP有粘包现象,UDP永远不会粘包 粘包不一定会发生 如果发生了:1.可能是在客户端已经粘了 2.客户端没有粘,可能是在服务端粘了 首先需要掌握一个socket收发消息的原 ...
- python网络编程-socket“粘包”(小数据发送问题)
一:什么是粘包 “粘包”, 即服务器端你调用时send 2次,但你send调用时,数据其实并没有立刻被发送给客户端,而是放到了系统的socket发送缓冲区里,等缓冲区满了.或者数据等待超时了,数据才会 ...
- Python之路 - 网络编程之粘包
Python之路 - 网络编程之粘包 粘包
- python/socket编程之粘包
python/socket编程之粘包 粘包 只有TCP有粘包现象,UDP永远不会粘包. 首先需要掌握一个socket收发消息的原理 发送端可以是1k,1k的发送数据而接受端的应用程序可以2k,2k的提 ...
- python 网络编程 TCP/IP socket UDP
TCP/IP简介 虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多. 计算机为了联网,就必须规定通信协议,早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Micro ...
- python socket网络编程之粘包问题详解
一,粘包问题详情 1,只有TCP有粘包现象,UDP永远不会粘包 你的程序实际上无权直接操作网卡的,你操作网卡都是通过操作系统给用户程序暴露出来的接口,那每次你的程序要给远程发数据时,其实是先把数据从用 ...
- Python全栈-网络编程-TCP粘包
一.什么是TCP粘包 C/S架构下,接收方不知道每个消息的发送间隙.也不知道每次应该提取多少个字节的数据,与此同时,TCP是面向连接的,面向流的,收发两端都要有,因此发送端为了将多个发往接收端的数据包 ...
- 《Python网络编程》学习笔记--UDP协议
第二章中主要介绍了UDP协议 UDP协议的定义(转自百度百科) UDP是OSI参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成,提供面向事务 ...
- UNIX网络编程——Socket粘包问题
一.两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通讯连接,连接建立后不断开, 然后再进行报文发送和接收. 2.短连接 Client方与Server每进行一次报文收发交易 ...
随机推荐
- Spring源码由浅入深系列四 创建BeanFactory
继上一章refresh之后,上图描述了obtainFreshBeanFactory过程.
- CodeForces1249B1/B2-Books Exchange-dfs-一般搜索+记忆化搜索
一般搜索 注意:一般定义成void Books Exchange (easy version) CodeForces - 1249B2 The only difference between eas ...
- Codeforces 1176A Divide it!
题目链接:http://codeforces.com/problemset/problem/1176/A 思路:贪心,对第二个操作进行俩次等于将n变成n/3,第三个操作同理,我们将n不断除以2,再除以 ...
- 20140312 Excel表格画折现图次坐标轴
1.struct 是8字节对齐 2.char * a, sizeof(a)=4; char a[]="abcdefg";sizeof(a)=8; 3.内存对其齐
- js 事件驱动原理
还记得当初学JAVA-GUI编程时学习过事件监听机制,此时再学习JavaScript中的事件驱动机制,不免简单.当初学习时也是画过原理图,所以从原理图开始吧! js是采用事件驱动(event-driv ...
- IntelliJ IDEA创建springboot项目
1.创建新项目. 2. 3.Group 是包名,Artifact是项目名. 4.springboot版本尽量选择最高版本,且不要选择SNAPSHOP版本. 5.路径可自定义,默认为D://IDEA/M ...
- Python匹马行天下之运算符
什么事运算符? 本章节主要说明Python的运算符.举个简单的例子 4 +5 = 9 . 例子中,4 和 5 被称为操作数,"+" 称为运算符. Python语言支持以下类型的运算 ...
- COGS2355 【HZOI2015】 有标号的DAG计数 II
题面 题目描述 给定一正整数n,对n个点有标号的有向无环图(可以不连通)进行计数,输出答案mod 998244353的结果 输入格式 一个正整数n 输出格式 一个数,表示答案 样例输入 3 样例输出 ...
- mysql连接卡死,很多线程sleep状态,导致CPU中mysqld占用率极高
关闭所有 .................................. .连接: ##把全部的MySQL连接kill掉for i in $(mysql -uroot -p123456 -Bse ...
- thinkphp import标签
传统方式的导入外部JS和CSS文件的方法是直接在模板文件使用: 直线电机哪家好 <script type='text/javascript' src='/Public/Js/Util/Array ...