粘包问题

什么是粘包问题呢?

在我们写 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的更多相关文章

  1. Python网络编程,粘包、分包问题的解决

    tcp编程中的粘包.分包问题的解决: 参考:https://blog.csdn.net/yannanxiu/article/details/52096465 服务端: #!/bin/env pytho ...

  2. python网络编程之粘包

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

  3. python网络编程-socket“粘包”(小数据发送问题)

    一:什么是粘包 “粘包”, 即服务器端你调用时send 2次,但你send调用时,数据其实并没有立刻被发送给客户端,而是放到了系统的socket发送缓冲区里,等缓冲区满了.或者数据等待超时了,数据才会 ...

  4. Python之路 - 网络编程之粘包

    Python之路 - 网络编程之粘包 粘包

  5. python/socket编程之粘包

    python/socket编程之粘包 粘包 只有TCP有粘包现象,UDP永远不会粘包. 首先需要掌握一个socket收发消息的原理 发送端可以是1k,1k的发送数据而接受端的应用程序可以2k,2k的提 ...

  6. python 网络编程 TCP/IP socket UDP

    TCP/IP简介 虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多. 计算机为了联网,就必须规定通信协议,早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Micro ...

  7. python socket网络编程之粘包问题详解

    一,粘包问题详情 1,只有TCP有粘包现象,UDP永远不会粘包 你的程序实际上无权直接操作网卡的,你操作网卡都是通过操作系统给用户程序暴露出来的接口,那每次你的程序要给远程发数据时,其实是先把数据从用 ...

  8. Python全栈-网络编程-TCP粘包

    一.什么是TCP粘包 C/S架构下,接收方不知道每个消息的发送间隙.也不知道每次应该提取多少个字节的数据,与此同时,TCP是面向连接的,面向流的,收发两端都要有,因此发送端为了将多个发往接收端的数据包 ...

  9. 《Python网络编程》学习笔记--UDP协议

    第二章中主要介绍了UDP协议 UDP协议的定义(转自百度百科) UDP是OSI参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成,提供面向事务 ...

  10. UNIX网络编程——Socket粘包问题

    一.两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通讯连接,连接建立后不断开, 然后再进行报文发送和接收. 2.短连接 Client方与Server每进行一次报文收发交易 ...

随机推荐

  1. python脚本往redis加数据

    #-*-coding:utf-8-*-from rediscluster import StrictRedisClusterimport pymysqlimport timeimport cProfi ...

  2. Google Projectsheet Planning 插件的WBS

    生成 WBS的序列號 在 Sldebar中的 "WBS" 按鈕: "< WBS" 取消下級目錄 "WBS >" 生成下級目錄 G ...

  3. bzoj1568 Blue Mary

    题意:P:加入一条一次函数.Q:询问x位置的最大函数值. 标程: #include<bits/stdc++.h> using namespace std; ; int q,x,n; dou ...

  4. C++相对路径和绝对路径

    学习备忘 转自:http://www.cnblogs.com/vranger/p/3820783.html 电脑硬盘E盘下,建文件夹“test”,"test"下建立子文件夹“fil ...

  5. memset 初始化 不同数值 打表

    #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #in ...

  6. leetcood学习笔记-55-跳跃游戏

    题目描述: 第一次提交: class Solution: def canJump(self, nums: List[int]) -> bool: if len(nums)<=1: retu ...

  7. 解析Mybatis入门第二天

    入门第二天 目的:使用Mybatis对数据库中的数据进行简单的操作.例如:增.删.改.查. 前言:同样是使用idea创建一个普通的maven工程(如何创建一个普通的Maven工程可以参考入门第一天的详 ...

  8. 页面JS缓存问题解决方案

    .在jsp中加入头 <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <META HTTP-EQUI ...

  9. LUOGU P2860 [USACO06JAN]冗余路径Redundant Paths (双联通,缩点)

    传送门 解题思路 刚开始是找的桥,后来发现这样不对,因为一条链就可以被卡.后来想到应该缩点后找到度数为1 的点然后两两配对. #include<iostream> #include< ...

  10. 大杀器Bitset

    其实并不怎么会用,有一次有位学长提到了这个名字,就这么取题目了. 1.BZOJ 3687 简单题 求子集的算术和的异或和 http://www.lydsy.com/JudgeOnline/proble ...