-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient04.py
More file actions
91 lines (78 loc) · 2.91 KB
/
client04.py
File metadata and controls
91 lines (78 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# -*- coding: UTF-8 -*- #
"""
@filename:client04.py
@author:Ning
@time:2022-07-14
"""
import socket
import struct
import subprocess
'''
本代码仅为了测试改进后的shell代码效果,无实际用途
#################################################################################################
struct模块可以把一个类型转换为固定长度的bytes
解决粘包思路:
通过struck模块将需要发送的内容的长度进行打包,打包成一个4字节长度的数据发送到对端,
对端只要取出前4个字节,然后对这四个字节的数据进行解包,
拿到你要发送的内容的长度,然后通过这个长度来继续接收我们实际要发送的内容。
'''
#执行命令函数代码
def exec_cmd(command):
"""执行命令函数"""
obj = subprocess.Popen(command.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
stdout_res = obj.stdout.read() + obj.stderr.read()
return stdout_res
def recv_data(sock,buf_size=1024):
"""解决粘包"""
#先接收命令执行结果的长度
x = sock.recv(4)
all_size = struct.unpack('i',x)[0]
#将服务器传递过来的整体data大小数值赋值给all——size
'''
struct.unpack方法,先接收对端发送的四个字节,然后通过unpack将该四字节转换为
对应格式的元组
x --- pad byte c --- char b --- signed char
B --- unsigned char h --- short H --- unsigned short
i --- int I --- unsigned int l --- long
L --- unsigned long q --- long long Q --- unsigned long long
f --- float d --- double s = char[] (string)
p = char[] P void * integer
#接收真实的数据
'''
recv_size = 0
#接收数据大小
data = b''
'''
如果当前可接收的数据大小还未到对面最大值的数据大小,则继续接收并输出
'''
while recv_size < all_size:
data += sock.recv(buf_size)
recv_size += buf_size
return data
def send_data(sock, data):
"""发送数据也解决粘包问题"""
if type(data) == str:
data = data.encode("utf-8")
# 新增发送命令的粘包解决方案
# 计算命令长度 , 打包发送
cmd_len = struct.pack('i', len(data))
sock.send(cmd_len)
# 发送命令
sock.send(data)
def main():
client = socket.socket()
client.connect(('127.0.0.1',8888))
while 1:
try:
cmd = recv_data(client)
if cmd == b"q":break
#加入判断,如果返回消息为q,则终止循环,退出聊天
res = exec_cmd(cmd)
#非空且不退出,则将传入的cmd变量值传到执行命令方法中
send_data(client,res)
except Exception:
break
client.close()
if __name__ == '__main__':
main()