python中的黏包问题和非黏包问题主要是tcp和udp的区别,tcp都是可靠传输需要建立链接进行传输信息是全双工通信的,udp是不可靠传输不需要建立链接进行通信,两者具有很明显的差别。
1.socket中使用tcp建立链接出现的黏包现象,实现的是远程启动cmd命令,在服务端向客户端发送cmd命令,客户端返回执行结果
server端代码
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,addr = sk.accept()
while True:
cmd = input('>>>')
conn.send(bytes(cmd,encoding='utf-8'))
ret = conn.recv(1024)
print(ret.decode('gbk'))
conn.close()
sk.close()
client端代码
import socket
import subprocess
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
while True:
cmd = sk.recv(1024)
print(cmd.decode('utf-8'))
ret = subprocess.Popen(
cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
msg = ret.stdout.read().decode('gbk')
msg1 = 'stdout: ' + msg
msg2_err = ret.stderr.read().decode('gbk')
msg3_err = 'stderr' + msg2_err
sk.send(bytes(msg1,encoding='gbk'))
sk.send(bytes(msg3_err,encoding='gbk'))
sk.close()
当我们连续输入 dir:ls dir dir 就会出现下面这种状况
D:\python3\python.exe D:/pystudy/pythonject1/day31/粘包问题/server.py
>>>dir:ls
stdout: 驱动器 D 中的卷是 新加卷
卷的序列号是 8A4B-FE3E
D:\pystudy\pythonject1\day31\粘包问题 的目录
>>>dir
stderr找不到文件
>>>dir
stdout: 驱动器 D 中的卷是 新加卷
卷的序列号是 8A4B-FE3E
D:\pystudy\pythonject1\day31\粘包问题 的目录
2021/08/06 21:37 <DIR> .
2021/08/06 21:37 <DIR> ..
2021/08/06 21:37 1,123 client.py
2021/08/06 20:11 266 server.py
2021/08/06 14:10 0 __init__.py
3 个文件 1,389 字节
2 个目录 54,143,066,112 可用字节
stderr
>>>
我们会发现上面的情况是当上一次的查询结果没有发完整的时候下一次再发送的时候会继续把没有发完的发过来,这就是黏包现象。
2.基于udp实现上面的功能不会出现黏包的现象但是会出现丢包的现象下面是代码部分
server_udp端代码
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',8080))
while True:
msg,addr = sk.recvfrom(1024)
print(msg.decode('utf-8'))
info = input('>>>')
sk.sendto(bytes(info,encoding='utf-8'),addr)
msg,addr = sk.recvfrom(1024)
print(msg.decode('gbk'))
sk.close()
client_udp 端代码
import socket
import subprocess
sk = socket.socket(type=socket.SOCK_DGRAM)
ip_port = ('127.0.0.1',8080)
sk.sendto(bytes('你好我是clien',encoding='utf-8'),ip_port)
while True:
cmd,addr = sk.recvfrom(1024)
ret = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
msg1 = 'stdout: ' + ret.stdout.read().decode('gbk')
msg2 = 'stderr: ' + ret.stderr.read().decode('gbk')
sk.sendto(bytes(msg1,encoding='gbk'),addr)
sk.sendto(bytes(msg2,encoding='gbk'),addr)
sk.close()
输入ipconfig 控制台输出
D:\python3\python.exe D:/pystudy/pythonject1/day31/粘包问题/server_udp.py
你好我是clien
>>>ipconfig
stdout:
Windows IP 配置
以太网适配器 以太网:
媒体状态 . . . . . . . . . . . . : 媒体已断开连接
连接特定的 DNS 后缀 . . . . . . . :
无线局域网适配器 本地连接* 1:
媒体状态 . . . . . . . . . . . . : 媒体已断开连接
连接特定的 DNS 后缀 . . . . . . . :
无线局域网适配器 本地连接* 2:
媒体状态 . . . . . . . . . . . . : 媒体已断开连接
连接特定的 DNS 后缀 . . . . . . . :
无线局域网适配器 WLAN:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe80::7460:f48d:1034:e5d3%17
IPv4 地址 . . . . . . . . . . . . : 192.168.1.107
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 192.168.1.1
stderr:
>>>
很明显上面的stderr后面还有内容没有输出完,下面我们继续输入dir看控制台输出的内容
默认网关. . . . . . . . . . . . . : 192.168.1.1
stderr:
>>>dir
stdout: 驱动器 D 中的卷是 新加卷
卷的序列号是 8A4B-FE3E
D:\pystudy\pythonject1\day31\粘包问题 的目录
2021/08/07 14:35 <DIR> .
2021/08/07 14:35 <DIR> ..
2021/08/06 22:28 1,085 client.py
2021/08/07 14:34 545 client_udp.py
2021/08/06 20:11 266 server.py
2021/08/07 14:35 317 server_udp.py
2021/08/06 14:10 0 __init__.py
5 个文件 2,213 字节
2 个目录 54,138,503,168 可用字节
stderr:
>>>
很明显发现ipconfig的内容没有继续输出而是直接输出dir的内容,这就是tcp和udp连接的区别,tcp可以保证数据的可靠性,但是udp只输出最大可接收的内容不会将超出的部分继续输出
|