Python网络编程之简单SSH交互

  • server.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
import socket
import subprocess

ip_port = ('127.0.0.1', 5555)

# step 1: 创建socket套接字, 里面封装了通信协议
s = socket.socket()

# step 2: 绑定IP及端口号
s.bind(ip_port)

# step 3: 监听绑定的端口
s.listen(5)

# 把接收客户端连接请求的操作循环起来就可以接受多个用户的请求啦
# 注意:同一时间只能处理一个客户端的请求,其他连接上的用户会排队等待
# 最后支持多少个用户排队等待,是由listen中的参数决定的(连接池)
while True:

# 等待客户端的连接(阻塞函数)
# step 4: 接受客户端的连接
conn, addr = s.accept()
# conn对象里封装了连接过来的这个客户端的通信线路信息
# 后期跟这个客户端的通信与交互都需要在conn这条通信线路上进行

while True:

# step 5: 接收消息(在conn通道没有被关闭的情况下是阻塞的函数,一旦conn被客户端关闭,该函数将不会阻塞)
recv_data = conn.recv(1024)

# 如果conn通道被客户端主动关闭,recv函数将不再阻塞,recv_data将接收到空字符串
# 通过判断recv_data为空字符串来退出服务端的连接
if len(recv_data) == 0: break

# step 6:处理消息
cmd = str(recv_data, encoding='utf-8')
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
res = p.stdout.read()
send_data = str(res, encoding='utf-8')

# step 7: 发送消息
conn.send(bytes(send_data, encoding='utf-8'))

# step 8: 断开连接
conn.close()

服务端在接收消息之后,拿到系统中去执行,取回标准输出,这里需要特别注意一下字符编码的问题。

在不同的系统中,字符编码可能不一样,如果是Windows平台,字符编码可能是gbk,在linux系统中,字符编码可能是GB18030``zh_CN.UTF-8等等,在这些系统中执行完命令后,回显的字符编码与系统是一致的,我们需要把回显的字节按照系统的编码类型进行编码并转化成Python的string字符类型,由Python的字符串作为中间人去帮我们做转换

类似于这样的过程 gbk ---> str ---> utf-8

  • client.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
import socket

ip_port = ('127.0.0.1', 5555)

# step 1: 创建socket套接字, 里面封装了通信协议
s = socket.socket()

# step 2: 连接服务端
s.connect(ip_port)

while True:

# step 3: 发送消息
send_data = input("> ").strip()

# 如果客户端输入了exit,退出循环,主动close掉与服务端的连接
if send_data == "exit": break

# 如果什么也没有输入,重新循环接收输入
if len(send_data) == 0: continue

# 这里注意,和服务端不同的是,服务端找到对端是通过conn对象,而客户端是s对象
# 在Python3.x中,socket对象发送对象必须是字节类型(2.7中可以是字符串)
s.send(bytes(send_data, encoding='utf-8'))

# step 4: 收消息
recv_data = s.recv(1024)
print(str(recv_data, encoding='utf-8'))

# step 5: 断开连接
s.close()

提示:上面只对可以正确执行的系统命令做了处理,如果输入了一个错误的命令,那么stdout标准输出根本不会捕捉到,所以会出现问题