Python--网络编程-----粘包现象

一、为了防止出现端口占用的情况,

linux中可以使用pkill -9 python

windows系统中使用taskkill python

二、什么是粘包现象

1、多个包(也就是多个命令的执行结果)粘在一起的现象,叫做粘包现象

2、代码示例如下:

服务端代码:

 1 import socket
 2 import subprocess
 3 
 4 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 5 # phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 6 phone.bind(('127.0.0.1', 9081))  # 0-65535:0-1024给操作系统使用
 7 phone.listen(5)
 8 
 9 print('starting......')
10 while True:  # 链接循环
11     conn, client_addr = phone.accept()
12     print(client_addr)
13 
14     while True:  # 通信循环
15         try:
16             # 1、收命令
17             cmd = conn.recv(1024)
18             if not cmd:  # 适用于linux操作系统
19                 break
20             print('客户端的数据', cmd)
21 
22             # 2、执行命令,拿到结果
23             obj = subprocess.Popen(cmd.decode('utf-8'), shell=True,
24                                    stdout=subprocess.PIPE,
25                                    stderr=subprocess.PIPE)
26 
27             stdout = obj.stdout.read()
28             stderr = obj.stderr.read()
29             # 3、把命令的结果返回给客户端
30             print(len(stdout) + len(stderr))
31             conn.send(stdout+stderr)
32 
33         except ConnectionResetError:  # 适用于Windows操作系统
34             break
35 
36     conn.close()
37 
38 phone.close()

客户端代码:

 1 import socket
 2 
 3 
 4 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 5 
 6 phone.connect(('127.0.0.1', 9081))
 7 
 8 while True:
 9     # 1、发命令
10     cmd = input('>>:').strip()
11     if not cmd:
12         continue
13     phone.send(cmd.encode('utf-8'))
14 
15     # 2、拿命令的结果,打印
16     data = phone.recv(1024)
17     print(data.decode('gbk'))
18 
19 phone.close()

在客户端依次输入dir,ipconfig,dir,

客户端运行结果为:

 1 C:Usersxu516PycharmProjectsPython全栈开发venvScriptspython.exe "C:/Users/xu516/PycharmProjects/Python全栈开发/第三模块/网络编程/04 粘包现象/客户端.py"
 2 >>:dir
 3  驱动器 C 中的卷是 OS
 4  卷的序列号是 7849-BAF9
 5 
 6  C:Usersxu516PycharmProjectsPython全栈开发第三模块网络编程4 粘包现象 的目录
 7 
 8 2018/04/07  22:17    <DIR>          .
 9 2018/04/07  22:17    <DIR>          ..
10 2018/04/05  21:18                 0 __init__.py
11 2018/04/07  22:17               376 客户端.py
12 2018/04/07  22:17             1,194 服务端.py
13                3 个文件          1,570 字节
14                2 个目录 36,304,265,216 可用字节
15 
16 >>:ipconfig
17 
18 Windows IP 配置
19 
20 
21 无线局域网适配器 本地连接* 3:
22 
23    媒体状态  . . . . . . . . . . . . : 媒体已断开连接
24    连接特定的 DNS 后缀 . . . . . . . : 
25 
26 以太网适配器 VMware Network Adapter VMnet1:
27 
28    连接特定的 DNS 后缀 . . . . . . . : 
29    本地链接 IPv6 地址. . . . . . . . : fe80::5d54:4c1:d7d6:c647%6
30    IPv4 地址 . . . . . . . . . . . . : 192.168.189.1
31    子网掩码  . . . . . . . . . . . . : 255.255.255.0
32    默认网关. . . . . . . . . . . . . : 
33 
34 以太网适配器 VMware Network Adapter VMnet8:
35 
36    连接特定的 DNS 后缀 . . . . . . . : 
37    本地链接 IPv6 地址. . . . . . . . : fe80::680e:7f79:aed1:fe62%10
38    IPv4 地址 . . . . . . . . . . . . : 192.168.254.1
39    子网掩码  . . . . . . . . . . . . : 255.255.255.0
40    默认网关. . . . . . . . . . . . . : 
41 
42 无线局域网适配器 WLAN:
43 
44    连接特定的 DNS 后缀 . . . . . . . : DHCP HOST
45    本地链接 IPv6 地址. . . . . . . . : fe80::9c84:419c:e3af:89dd%11
46    IPv4 地址 . . . . . . . . . . . . : 192.168.0.106
47    子网掩码  . . . . . . . . . . . . : 255.255.255.0
48    
49 >>:dir
50 默认网关. . . . . . . . . . . . . : 192.168.0.1
51 
52 以太网适配器 蓝牙网络连接:
53 
54    媒体状态  . . . . . . . . . . . . : 媒体已断开连接
55    连接特定的 DNS 后缀 . . . . . . . : 
56 
57 隧道适配器 Teredo Tunneling Pseudo-Interface:
58 
59    连接特定的 DNS 后缀 . . . . . . . : 
60    IPv6 地址 . . . . . . . . . . . . : 2001:0:9d38:953c:20d3:83ef:d86a:f024
61    本地链接 IPv6 地址. . . . . . . . : fe80::20d3:83ef:d86a:f024%2
62    默认网关. . . . . . . . . . . . . : ::
63 
64 >>:

第一次输入dir显示结果正常,第二次输入dir输出结果却为ip地址信息,也就是上一个ifconfig命令的遗留信息,这种现象就叫做粘包现象,

代码中服务端和客户端recv指定的最大接收字节数都为1024个字节,我们可以在服务端上看看命令执行结果的长度,如下:

1 starting......
2 ('127.0.0.1', 60296)
3 客户端的数据 b'dir'
4 453
5 客户端的数据 b'ipconfig'
6 1481
7 客户端的数据 b'dir'
8 453

可以看出,ipconfig命令结果的长度超出了recv最大接收字节数,没有接收完,还遗留在管道里,就出现了粘包现象

原文地址:https://www.cnblogs.com/xudachen/p/8735270.html