0

我正在 python (3.4.4) 中创建一个通信平台并使用multiprocessing.managers.BaseManager类。我已将问题隔离到下面的代码中。

目的是让ROVManager(role='server')实例在主计算机上的一个进程中运行,并为在同一台计算机上运行的多个ROVManager(role='client')实例提供系统字典的读/写功能,并且连接到同一网络的 ROV(遥控车辆)。这样,多个客户端/进程可以执行不同的任务,例如读取传感器值、移动电机、打印、记录等,所有这些都使用同一个字典。下面的start_reader()就是这些客户端之一。

代码

from multiprocessing.managers import BaseManager
import multiprocessing as mp
import sys    

class ROVManager(BaseManager):
    def __init__(self, role, address, port, authkey=b'abc'):
        super(ROVManager, self).__init__(address=(address, port),
                                         authkey=authkey)
        if role is 'server':
            self.system = {'shutdown': False}
            self.register('system', callable=lambda: self.system)
            server = self.get_server()
            server.serve_forever()
        elif role is 'client':
            self.register('system')
            self.connect()    

def start_server(server_ip, port_var):
    print('starting server')
    ROVManager(role='server', address=server_ip, port=port_var)    

def start_reader(server_ip, port_var):
    print('starting reader')
    mgr = ROVManager(role='client', address=server_ip, port=port_var)
    i = 0
    while not mgr.system().get('shutdown'):
        sys.stdout.write('\rTotal while loops: {}'.format(i))
        i += 1    

if __name__ == '__main__':
    server_p = mp.Process(target=start_server, args=('0.0.0.0', 5050))
    reader_p = mp.Process(target=start_reader, args=('127.0.0.1', 5050))
    server_p.start()
    reader_p.start()
    while True:
        # Check system status, restart processes etc here
        pass

错误

这会导致以下输出和错误:

starting server
starting reader
Total while loops: 15151
Process Process - 2:
Traceback(most recent call last):
    File "c:\python34\Lib\multiprocessing\process.py", line 254, in _bootstrap
        self.run()
    File "c:\python34\Lib\multiprocessing\process.py", line 93, in run 
        self._target(*self._args, **self._kwargs)
    File "C:\git\eduROV\error_test.py", line 29, in start_reader
        while not mgr.system().get('shutdown'):
    File "c:\python34\Lib\multiprocessing\managers.py", line 640, in temp
        token, exp = self._create(typeid, *args, **kwds)
    File "c:\python34\Lib\multiprocessing\managers.py", line 532, in _create
        conn = self._Client(self._address, authkey=self._authkey)
    File "c:\python34\Lib\multiprocessing\connection.py", line 496, in Client
        c = SocketClient(address)
    File "c:\python34\Lib\multiprocessing\connection.py", line 629, in SocketClient
        s.connect(address)
OSError: [WinError 10048] Only one usage of each socket address(protocol / network address / port) is normally permitted

我的研究

总的 while 循环通常在 15000-16000 范围内。据我了解,每次调用 mgr.system().get('shutdown')时似乎都会创建和终止一个套接字。然后 Windows 会用完可用的套接字。我似乎找不到设置socket.SO_REUSEADDR的方法。

有没有办法解决这个问题,或者经理不是为这种沟通而生的?谢谢 :)

4

1 回答 1

0

正如错误 Only one usage of each socket address一般表明的那样,您可以/应该只将一个进程绑定到一个套接字(除非您相应地设计您的应用程序,通过SO_REUSEADDR在创建套接字时传递选项)。这些行

server_p = mp.Process(target=start_server, args=('0.0.0.0', 5050))
reader_p = mp.Process(target=start_reader, args=('127.0.0.1', 5050))

在同一个端口上创建两个进程5050&所以错误。
您可以在此处参考以了解如何使用SO_REUSEADDR及其含义,但我引用的主要部分应该让您继续前进

第二个套接字调用 setsockopt 时将 optname 参数设置为 SO_REUSEADDR 并将 optval 参数设置为布尔值 TRUE,然后在与原始套接字相同的端口上调用 bind。一旦第二个套接字成功绑定,绑定到该端口的所有套接字的行为都是不确定的。例如,如果同一端口上的所有套接字都提供 TCP 服务,则无法保证通过该端口传入的任何 TCP 连接请求都由正确的套接字处理——这种行为是不确定的。

于 2018-02-09T14:03:25.760 回答