PYTHON——TCP&UDP:Socket实现远程执行命令

  本文介绍客户端client输入dos指令,并将dos指令发送给服务端server,服务端接收到指令,通过调用subprocess模块的Popen方法实例化一个子进程对象,子进程对象执行完指令后,将结果并通过管道方式回送到主进程。其中,subprocess的用法,参见:Python subprocess模块解析

一、通过发送字符串长度的方法:

1、服务端程序:cmd_server.py:

import socket
import subprocess
import time
# subprocess.Popen() 重要方法. # 学socket的秘籍:一收一发 sk = socket.socket() host='' #空表示本机,等效于127.0.0.1和localhost port=8000 address = (host,port) sk.bind(address) sk.listen(3) print('waiting......') # conn,addr = sk.accept() #这个conn是客户端的socket对象。非常重要。 while True: conn, addr = sk.accept() # 这个conn是客户端的socket对象。非常重要。 print(addr) while True: try: data = conn.recv(1024) except Exception: break if not data: #客户端退出时,最后还是会给服务端发送一个空串。即data为空。 break print('--------->',str(data,'utf8')) obj=subprocess.Popen(str(data,'utf8'),shell=True,stdout=subprocess.PIPE) cmd_result = obj.stdout.read() #bytes类型 result_len = bytes(str(len(cmd_result)),'utf8') conn.sendall(result_len) #必须先传一个长度过去
# time.sleep(1) #两个发送指令send或sendall连在一起,会出现粘包现象。解决粘包现象,就是加入sleep
     conn.recv(1024) #通过一收一发方式,多引入一个短收,解决粘包问题。
conn.sendall(cmd_result)
conn.close()

2、客户端程序:cmd_client.py:

import socket

sk=socket.socket()
address = ('127.0.0.1',8000)
sk.connect(address)

while True:
    inp = input('>>>')
    if inp=='exit':
        break
    sk.send(bytes(inp,'utf8'))
    result_len = int(str(sk.recv(1024),'utf8'))
sk.send(bytes('ok')) #用于解决粘包现象
print(result_len) data=bytes() #初始化一个bytes类型的变量,就像初始化sum=0一样 while len(data)!=result_len: temp = sk.recv(1024) data += temp print(str(data,'gbk')) sk.close()

二、更好的方法:

1、服务端程序:cmd_server.py:

import socket
import subprocess

# subprocess.Popen() 重要方法.
# 学socket的秘籍:一收一发
sk = socket.socket()
host=''  #空表示本机,等效于127.0.0.1和localhost
port=8000
address = (host,port)
sk.bind(address)
sk.listen(3)
print('waiting......')
# conn,addr = sk.accept()  #这个conn是客户端的socket对象。非常重要。

while True:
    conn, addr = sk.accept()  # 这个conn是客户端的socket对象。非常重要。
    print(addr)
    while True:
        try:
            data = conn.recv(1024)
        except Exception:
            break
        if not data:  #客户端退出时,最后还是会给服务端发送一个空串。即data为空。
            break
        print('--------->',str(data,'utf8'))
        obj=subprocess.Popen(str(data,'utf8'),shell=True,stdout=subprocess.PIPE)
        cmd_result = obj.stdout.read()  #bytes类型
# result_len = bytes(str(len(cmd_result)),'utf8')
# conn.sendall(result_len) #必须先传一个长度过去
# conn.recv(1024) #两个发送指令send或sendall连在一起,可能会出现粘包现象。解决粘包现象,就是加入临时阻塞
conn.sendall(cmd_result)
conn.close()

2、客户端程序:cmd_client.py

import socket

sk=socket.socket()
address = ('127.0.0.1',8000)
sk.connect(address)
buffersize=1024
while True:
    inp = input('>>>')
    if inp=='exit':
        break
    sk.send(bytes(inp,'utf8'))
    fullDataBtyes = b''  #初始化一个bytes类型的变量,等效于fullDataBytes=bytes()。
    while True:
        data = sk.recv(buffersize)
        fullDataBtyes += data
        if len(data)<buffersize:
            break;
    print(str(fullDataBtyes,'gbk'))

    # result_len = int(str(sk.recv(1024),'utf8'))
    # sk.send(bytes('ok')) #解决粘包
    # print(result_len)
    # data=bytes()  #初始化一个bytes类型的变量,就像初始化sum=0一样
    # while len(data)!=result_len:
    #     temp = sk.recv(1024)
    #     data += temp
    # print(str(data,'gbk'))

sk.close()

参考:

1、‘’老男孩‘’python全栈开发,袁老师讲解

2、参考《python从菜鸟到高手》,作者:李宁

猜你喜欢

转载自www.cnblogs.com/chenhaiming/p/9886288.html