day8-socket实现简单的ssh
实验简述
在上一个模块,我们了解可以通过socket封装底层协议对服务器端和客户端之间进行收发消息,实现通信,那么我们可以做一个客户端连接上服务端后,让服务器执行命令,并返回结果给客户端。下面我们就来实现该功能
服务器端

import socket,os #导入模块
server = socket.socket() #创建服务器实例
server.bind(("localhost",9995)) #绑定要监听的IP地址和端口
server.listen() #监听TCP传入连接
while True:
conn,addr = server.accept() #conn就是客户端连接过来在服务器端为其生成的一个连接实例(对象)
print("new conn:",addr)
while True:
data = conn.recv(1024) #接收客户端发送来的数据
if not data:
print("客户端已断开")
break
print("执行指令:",data.decode())
cmd_res = os.popen(data.decode()).read() #默认数据存储在I/O缓冲区
print("执行命令结果大小:",len(cmd_res))
if len(cmd_res) == 0:
cmd_res= "cmd没有正确输出。。。。"
conn.send(cmd_res.encode()) #发送数据到客户端(手动强制缓冲区超时去发送数据,默认等缓冲区填满再自动发送)
print("发送完成!")
server.close() #关闭服务器端
客户端

import socket
client = socket.socket() #创建客户端实例(对象)
client.connect(("localhost",9995)) #连接远程机器
while True:
cmd_input = input(">>:")
if len(cmd_input) == 0:
continue
client.send(cmd_input.encode()) #发送数据到远端
data = client.recv(1024) #从远端接收数据
print(data.decode())
client.close() #关闭客户端
执行过程
服务器端

客户端

通过以上在客户端上执行pwd命令后都能正常返回命令在服务器端执行的结果,但是当我们使用ifconfig返回的命令结果和接下来执行的ls命令时显示的结果却是上一次ifconfig没有输出完成的结果,这是为什么呢?
解析:用户第一次执行pwd命令时,命令执行的结果被存储在I/O缓冲区中,代码后面因为又执行了send操作,所以我们可以在客户端接收返回的结果,同样执行ifconfig时,服务器端将命令ifconfig执行的结果通过send全部发送到客户端(默认情况下结果存储在服务器缓冲区),而客户端因为默认情况下,一次最多只能接收1024B=1KB大小的数据,其客户端没有接收的数据存储在服务器端的I/O缓冲区,那么什么时候此缓冲区的数据能全部发送到客户端呢?
- 第一种情况:等待下一次服务器端再向客户端send数据时(手动强制缓冲区超时),只有当I/O缓冲区的数据全部发送完成,才会发送新的数据,也就是说,只有当ifconfig在I/O缓冲区里面的数据全部发送到客户端,ls执行的命令结果才会在客户端显示。
- 第二种情况:等到此缓冲区被填满后,才会触发系统调用接口,自动发送数据到客户端。
产生的问题
ifconfig命令产生的结果大小为3237B,按照客户端每次默认只能接收1024B大小的数据,那么我们如何让客户端接收全部的命令返回结果呢?
解决思路:服务器端向客户端发送数据之前,首先计算服务端执行命令的结果的大小,然后将执行命令结果的大小发送给客户端,而客户端根据结果大小使用多次循环接收,直到接收全部数据。

浙公网安备 33010602011771号