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
|
import
SocketServer
import
commands #使用其中的getstatusoutput()函数,让Server端可以识别Client端发送过来的命令并执行
import
time #主要使用其中的time.sleep()函数,用来解决Server端发送数据的“连块”问题
class
MySockServer(SocketServer.BaseRequestHandler):
def handle(self):
print
'Got a new connection from'
, self.client_address
while
True:
cmd = self.request.recv(
1024
)
if
not cmd:
print
'Last connection with:'
,self.client_address
break
cmd_result = commands.getstatusoutput(cmd) #获取Client端的指令并执行,返回结果是一个存储两个元素的元组,第一个元素为
0
表示成功执行,第二个元素则是命令的执行结果
self.request.send(str(len(cmd_result[
1
]))) #发送命令执行结果的大小长度,Client端要想接收任意大小的执行结果,就需要根据命令执行结果的大小来选择策略,这里需要注意的是,发送的数据是字符串,所以需要作类型转换
time.sleep(
0.2
) #睡眠
0
.2s,是为了解决“连块”的问题
self.request.sendall(cmd_result[
1
]) #发送命令执行结果
if
__name__ ==
'__main__'
:
HOST =
''
PORT =
50007
s = SocketServer.ThreadingTCPServer((HOST, PORT), MySockServer)
s.serve_forever()
|
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
|
import
socket
HOST =
'192.168.1.13'
PORT =
50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
def data_all(obj, lenth_size):
data =
''
#用来存储每一次循环时socket接收的数据,解决socket大概两万多字节的缓冲瓶颈限制
while
lenth_size !=
0
: #如果接收的数据长度不为
0
,开始执行接收数据处理策略
if
lenth_size <=
4096
: #这里以
4096
为单位块,作为每次的数据处理量大小
data_recv = obj.recv(lenth_size) #通过recv()接收数据
lenth_size =
0
#通过这一步的处理,数据全部接收完毕,置lenth_size为
0
,结束循环,完成数据的接收处理工作
else
:
data_recv = obj.recv(
4096
) #以
4096
为单位块,一次接收
4096
的数据量大小
lenth_size -=
4096
#处理完一次
4096
字节的数据后,将lenth_size减去
4096
data += data_recv #判断外层,用本地的data来存储接收到的数据,因为本地的data大小没有限制,所以不存在data饱和无法继续存储数据的问题,但前面socket的recv()函数一次最多只能接收的数据量大小是有限制的,这取决于socket的缓冲区大小,因此data_all函数的作用就是通过使用多次recv()函数,并且每次接收一定量的数据后就进行本地存储,直到把所有的数据都接收完毕
return
data
while
True:
user_input = raw_input(
'cmd to send:'
).strip()
if
len(user_input) ==
0
:
continue
s.sendall(user_input)
data_size =
int
(s.recv(
1024
)) #得到命令执行结果的大小长度,因为发送过来的数据是字符串,所以这里要作类型转换
print
'\033[32;1mdata size:\033[0m'
,data_size #打印命令执行结果的大小
result = data_all(s, data_size) #通过data_all函数来执行相应的数据接收处理策略
print result #打印命令执行结果
s.close() #关闭套接字
|
1
2
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day5$ python ssh_server5.py
===>光标在此处处于等待状态
|
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
|
xpleaf@xpleaf-machine:/mnt/hgfs/Python/day5$ python ssh_client5.py
cmd to send:df
data size:
502
===>命令执行结果的大小
df:
"/var/lib/lightdm/.gvfs"
: 权限不够 ===>命令的执行结果
文件系统 1K-块 已用 可用 已用% 挂载点
/dev/sda3
8781832
3458300
4877428
42
% /
udev
493784
4
493780
1
% /dev
tmpfs
201040
784
200256
1
% /run
none
5120
0
5120
0
% /run/lock
none
502592
144
502448
1
% /run/shm
/dev/sda1
93207
30139
58256
35
% /boot
.host:/
162256468
152391980
9864488
94
% /mnt/hgfs
cmd to send:pwd ===>执行pwd命令
data size:
21
/mnt/hgfs/Python/day5
cmd to send:ls
data size:
357
[
1
]sec_4_ver1(单线程,非交互式)
[
2
]sec_4_ver2(单线程,交互式,阻塞模式一般演示)
[
3
]sec_4_ver3(单线程,交互式,阻塞模式进阶演示)
[
4
]sec_4_ver3(单线程,交互式,多并发)
client4.py
duotiao_jian_biao3.py
jian_biao2.py
my_conn1.py
server4.py
ssh_client5.py
ssh_server5.py
Thread_socket_server4.py
cmd to send:top -bn
3
===>注意该命令的执行结果(大小)已经超出了socket的缓冲区大小,因此上面Client端中的程序代码主要就是为了解决该问题,这也是Client端的关键所在
data size:
34378
===>该命令的执行结果大小为三万多字节,超出了socket缓冲区,socket的recv()函数是无法一次接收那么多数据的
……
省略输出结果
cmd to send:ls ===>继续执行命令,返回结果正常
data size:
357
[
1
]sec_4_ver1(单线程,非交互式)
[
2
]sec_4_ver2(单线程,交互式,阻塞模式一般演示)
[
3
]sec_4_ver3(单线程,交互式,阻塞模式进阶演示)
[
4
]sec_4_ver3(单线程,交互式,多并发)
client4.py
duotiao_jian_biao3.py
jian_biao2.py
my_conn1.py
server4.py
ssh_client5.py
ssh_server5.py
Thread_socket_server4.py
|