python-3.x 从客户端关闭RPyC服务器

quhf5bfb  于 2023-01-27  发布在  Python
关注(0)|答案(2)|浏览(173)

我已经创建了一个RPyC服务器。连接正常,我所有公开的方法都正常。现在我想从客户端关闭服务器。这可能吗?安全不是问题,因为我不担心恶意连接关闭服务器。
其开头为(阻塞):

from rpyc import ThreadPoolServer
from service import MyService

t = ThreadPoolServer(MyService(), port=56565)
t.start()

现在我只需要关闭它。我还没有找到任何关于停止服务器的文档。

chhqkbe1

chhqkbe11#

您可以向Service类添加以下方法:

def exposed_stop(self):
    pid = os.getpid()

    if platform.system() == 'Windows':
        PROCESS_TERMINATE = 1
        handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, pid)
        ctypes.windll.kernel32.TerminateProcess(handle, -1)
        ctypes.windll.kernel32.CloseHandle(handle)
    else:
        os.kill(pid, signal.SIGTERM)

这将使服务获得自己的PID并发送SIGTERM给它自己。也许有一个更好的方法隐藏在API的某个黑暗角落里,但我没有找到更好的方法。
如果要在线程终止之前进行清理,可以设置退出陷阱:

t = rpyc.utils.server.ThreadedServer(service, port=port, auto_register=True)

# Set up exit traps for graceful exit.
signal.signal(signal.SIGINT, lambda signum, frame: t.close())
signal.signal(signal.SIGTERM, lambda signum, frame: t.close())

t.start() # blocks thread

# SIGTERM or SIGINT was received and t.close() was called
print('Closing service.')
t = None

shutil.rmtree(tempdir)
# etc.
qojgxg4l

qojgxg4l2#

如果有人感兴趣的话,我找到了另一种方法,我只是在全局范围内创建服务器对象,然后添加一个公开的方法来关闭它。

import rpyc
from rpyc.utils.server import ThreadedServer

class MyService(rpyc.Service):

    def exposed_stop(self):
        server.close()

    def exposed_echo(self, text):
        print(text)

server = ThreadedServer(MyService, port = 18812)

if __name__ == "__main__":

    print("server start")

    server.start()

    print("Server closed")

在客户端,由于连接被远程关闭,你会得到一个EOF错误,所以最好能捕捉到它。

import rpyc

c = rpyc.connect("localhost", 18812)
c.root.echo("hello")

try :
    c.root.stop()
except EOFError as e:
    print("Server was closed")

**EDIT:**我需要能够动态地指定服务器。所以我提供了这个(它更好吗?我不知道,但它工作得很好。不过要小心,如果你有多个服务器运行这个服务:事情可能变得怪异):

import rpyc
from rpyc.utils.server import ThreadedServer


class MyService(rpyc.Service):
    _server:ThreadedServer

    @staticmethod
    def set_server(inst=ThreadedServer):
        MyService._server = inst

    def exposed_stop(self):
        if self._server:
            self._server.close()

    def exposed_echo(self, text):
        print(text)

if __name__ == "__main__":

    server = ThreadedServer(MyService, port = 18812)
    MyService.set_server(server)
    
    print("server start")

    server.start()

    print("Server closed")

**PS:**使用Asynchronous Operations可能可以避免EOF错误

相关问题