Python - 在进程之间共享套接字

时间:2018-01-16 14:31:32

标签: python sockets twisted python-multiprocessing

是否可以在两个正在运行的进程之间共享套接字对象?

为了简化问题,假设我们有两个文件s1.pys2.py。两者都是在不同端口上侦听的tcp服务器。

s1.py body

from twisted.internet import reactor, protocol

CLIENTS = []

class Echo(protocol.Protocol):
    def connectionMade(self):
        CLIENTS.append(self)

    def dataReceived(self, data):
        self.transport.write(data)

    def connectionLost(self):
        CLIENTS.remove(self)

def main():
    factory = protocol.ServerFactory()
    factory.protocol = Echo
    reactor.listenTCP(8000, factory)
    reactor.run()

main()

和s2.py

from twisted.internet import reactor, protocol

class Echo(protocol.Protocol):

    def dataReceived(self, data):
        for socket in list_of_serialized_redis_CLIENTS_socket_object:
           socket.transport.write(data)

def main():
    factory = protocol.ServerFactory()
    factory.protocol = Echo
    reactor.listenTCP(8001, factory)
    reactor.run()

main()

是否可以与s1.py共享s1.py中的CLIENTS? 也许有一些方法可以序列化CLIENTS并将其存储在redis中。

1 个答案:

答案 0 :(得分:0)

使用socket.share()可能不像您想象的那么直截了当。 首先,它是Windows独有的功能,Windows是Twisted最少关注的平台。 在Twisted中访问低级socket对象可能很棘手,因为幕后发生了很多事情,如果更改可能会导致奇怪的结果。 换句话说,它确实可以走这条路,但不建议这样做。

如果您对新解决方案持开放态度,我认为RPC式服务器将解决您的问题。 我的想法是,由于连接对象位于s1中,因此只需创建一个远程进程即可实现"做东西"对那些联系。 其他进程可以连接到该服务器并在s1本地对象上执行函数。 Twisted' Perspective Broker是您可以利用的现成解决方案。

s1.py

from twisted.internet import reactor, protocol, endpoints
from twisted.spread import pb

class Echo(protocol.Protocol):
    def connectionMade(self):
        self.factory.client_set.add(self)

    def connectionLost(self, reason):
        self.factory.client_set.remove(self)

class Remote(pb.Root):
    def __init__(self, client_set):
        self.client_set = client_set

    def remote_s1_write(self, data):
        msg_tmpl = 'From s1...{0}'
        for client in self.client_set:
            response = msg_tmpl.format(data).encode('utf-8')
            client.transport.write(response)

def main():
    client_set = set()      # container will be shared between the 2 servers

    # setup Echo server
    factory = protocol.ServerFactory()
    factory.protocol = Echo
    factory.client_set = client_set
    echo_server = endpoints.TCP4ServerEndpoint(reactor, interface='localhost', port=8000)
    echo_server.listen(factory)

    # setup PB server
    pb_root = Remote(client_set)
    pb_factory = pb.PBServerFactory(pb_root)
    pb_server = endpoints.TCP4ServerEndpoint(reactor, interface='localhost', port=7999)
    pb_server.listen(pb_factory)

    reactor.run()

main()

s2.py

from twisted.internet import reactor, protocol, endpoints
from twisted.spread import pb

class Echo(protocol.Protocol):
    def dataReceived(self, data):
        remote = self.factory.pb_factory.getRootObject()
        remote.addCallback(lambda obj: obj.callRemote('s1_write', data))
        remote.addCallback(lambda echo: 's1 said: {0}'.format(data))
        remote.addErrback(lambda reason: 'error: {0}'.format(str(reason.value)))
        remote.addCallback(lambda response: print(response))
        self.transport.write(data)

def main():
    # connect to s1's PB server
    pb_factory = pb.PBClientFactory()
    pb_connection = endpoints.TCP4ClientEndpoint(reactor, host='localhost', port=7999)
    pb_connection.connect(pb_factory)

    # setup Echo server
    factory = protocol.ServerFactory()
    factory.protocol = Echo
    factory.pb_factory = pb_factory
    echo_server = endpoints.TCP4ServerEndpoint(reactor, interface='localhost', port=8001)
    echo_server.listen(factory)

    reactor.run()

main()

我采取了自由并更新了语法。试试这段代码,看看它是否有效,并询问您是否有任何问题。