一、为了防止出现端口占用的情况,
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:\Users\xu516\PycharmProjects\Python全栈开发\venv\Scripts\python.exe "C:/Users/xu516/PycharmProjects/Python全栈开发/第三模块/网络编程/04 粘包现象/客户端.py" 2 >>:dir 3 驱动器 C 中的卷是 OS 4 卷的序列号是 7849-BAF9 5 6 C:\Users\xu516\PycharmProjects\Python全栈开发\第三模块\网络编程\04 粘包现象 的目录 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最大接收字节数,没有接收完,还遗留在管道里,就出现了粘包现象