什么叫做黏包?
先写一个小补充:
encode()函数、decode()函数:
encode() 是将数据类型转换成bytes类型
decode()是将bytes类型转换成其他类型
encode() 叫做编码, decode( ) 叫做解码
通过一段代码来引出黏包现象(基于TCP的网络通信)
sever端
19
1
import socket
2
3
4
sk = socket.socket()
5
sk.bind(('127.0.0.1', 8080))
6
sk.listen()
7
8
conn, addr = sk.accept()
9
10
while True:
11
cmd = input('>>>')
12
conn.send((cmd.encode('utf-8'))) # 将输入的数据转换层(utf-8)的bytes类型,用于网络传输
13
14
ret = conn.recv(1024).decode('utf-8') # 将接收到的数据(utf-8)的bytes类型数据,解码成本身的数据类型
15
print(ret)
16
17
18
conn.close()
19
sk.close()
client端
20
1
import socket
2
import subprocess
3
4
5
sk = socket.socket()
6
sk.connect(('127.0.0.1', 8080))
7
while True:
8
cmd = sk.recv(1024).decode('utf-8')
9
ret = subprocess.Popen(cmd, shell=True,
10
stdout=subprocess.PIPE,
11
stderr=subprocess.PIPE)
12
13
std_out = 'stdout :' + (ret.stdout.read()).decode('gbk')
14
std_err = 'stderr :' + (ret.stderr.read()).decode('gbk')
15
print(std_out)
16
print(std_err)
17
sk.send(std_out.encode('utf-8'))
18
sk.send(std_err.encode('utf-8'))
19
20
sk.close()
仔细观察控制台这个时候会发现基于TCP连接从server端发送指令时,会接收一些并不完整的数据,在一次从server端发送指令时,client端会发送上一次断点的数据给server端,我们把这种现象叫做黏包!
基于UDP协议的黏包现象(ps:不存在)
udp_server
20
1
import socket
2
3
4
sk = socket.socket(type=socket.SOCK_DGRAM)
5
sk.bind(('127.0.0.1', 8091))
6
7
msg, addr = sk.recvfrom(1024)
8
9
while True:
10
cmd = input('>>>')
11
if cmd == 'q':
12
break
13
sk.sendto(cmd.encode('utf-8'), addr)
14
msg, addr = sk.recvfrom(1024) # 两次发送、两次接收
15
print(msg.decode('utf-8'))
16
msg, addr = sk.recvfrom(1024)
17
print(msg.decode('utf-8'))
18
19
20
sk.close()
udp_client
x
1
import socket
2
import subprocess
3
4
5
sk = socket.socket(type=socket.SOCK_DGRAM)
6
addr = ('127.0.0.1', 8091)
7
8
sk.sendto('吃了吗?'.encode('utf-8'), addr)
9
10
while True:
11
cmd, addr = sk.recvfrom(1024)
12
ret = subprocess.Popen(cmd.decode('gbk'), # 这里转码与解码的方式前后不一致,但发送过来的数据是英文。所以无妨!
13
shell=True,
14
stdout=subprocess.PIPE,
15
stderr=subprocess.PIPE
16
)
17
std_out = 'stdout: ' + (ret.stdout.read()).decode('gbk')
18
std_err = 'stderr: ' + (ret.stderr.read()).decode('gbk')
19
print(std_out)
20
print(std_err)
21
22
sk.sendto(std_out.encode('utf-8'), addr)
23
sk.sendto(std_err.encode('utf-8'), addr)
24
25
sk.close()
26