如果你看过了上篇文章ssh实现简单的数据传输,那么实现简单的ssh客户端也不是什么问题,无非就是在服务器端利用os模块将客户端发来的消息当作命令获取返回值,然后将返回值再发送给客户端,但是还是有些要注意的地方的,我先贴出来代码,然后再说注意的地方
服务器端
import socket
import os
# 生成socket实例
server = socket.socket()
# 绑定端口
server.bind(('localhost', 6969))
# 监听端口
server.listen()
# 等待链接
conn, addr = server.accept()
# 进入循环
while True:
print('等待指令')
# 接收指令
data = conn.recv(1024)
# 判断data是否存在
if not data:
print('断开')
break
# os模块获取指令
response = os.popen(data.decode()).read() # 获得返回 接受字符串,返回结果也是字符串
# popen无法获得错误返回值,所以加一步判断
if len(response) == 0:
response = 'Error'
# 发送返回值长度
conn.send(str(len(response.encode())).encode()) # len里面的response也要加一个.encode()
# 发送返回值
conn.send(response.encode())
print('send done')
server.close()
客户端
import socket
# 生成socket实例
client = socket.socket()
# 链接指定ip端口
client.connect(('localhost', 6969))
# 进入循环
while True:
# 获得指令
cmd = input('请输入指令:').strip()
# 指令为空继续等待输入
if len(cmd) == 0:
continue
# 发送指令
client.send(cmd.encode())
# 获得返回值长度
res_size = client.recv(1024).decode()
print(res_size)
# 字符串转整型
i_res_size = int(res_size)
# 一次收1024,判断收多少次,每收一次用总长度减去收到的长度,只要剩余长度大于0就一直收
while i_res_size > 0:
# 收取返回值,这里虽然写的1024但是每次收的有可能小于1024
data = client.recv(1024)
# 减去这一次收取的长度
i_res_size -= len(data) # 这里不能-1024 因为recv不一定每次都收1024 有可能小于1024
# 打印返回值
print(data.decode())
# 假如剩余长度小于等于0了说明收完了
else:
# 打印收取返回值的总长度
print('response recv done...', res_size)
这里有几个点要注意一下:
首先
ssh客户端输入命令时有的时候返回的值会大于1024,这样客户端一次收取不完,就会放置在缓冲区,下次输入命令就会返回缓冲区的数据而不是相应的数据,所以通过判断返回值长度的方法来循环收返回值直到将这一次的返回值收完
其次
os.popen接受的是字符串,返回的也是字符串
然后
服务器端发送返回值长度时,判断长度之前先encode()一下, 不然如果有汉字的话传输数据前跟传输数据后的长度会不一样,会导致无法判断收取次数
最后
客户端进入收数据循环之后虽然每次收的数据大小注明了是1024,但是不一定每次都是1024,所以减去的不能是1024而是每次收取的数据的长度
转载请注明出处
python自学技术互助扣扣群:670402334
下一篇:socket数据传输解决粘包问题
网友评论