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大小的数据,那么我们如何让客户端接收全部的命令返回结果呢?

解决思路:服务器端向客户端发送数据之前,首先计算服务端执行命令的结果的大小,然后将执行命令结果的大小发送给客户端,而客户端根据结果大小使用多次循环接收,直到接收全部数据。

posted @ 2017-10-25 21:44  Mr.hu  阅读(205)  评论(0编辑  收藏  举报