使用 Twisted 向现有 TCP 连接发送消息

Send message to existing TCP connection using Twisted

我正在编写一个 TCP 服务器来侦听包含来自远程机器的状态信息的 TCP 数据包。一旦建立,远程机器就会保持 TCP 连接。 以下是我的代码的重要部分:

#!/usr/bin/python
from twisted.internet import reactor, protocol
class FactoryProcess(protocol.Protocol):
    def dataReceived(self, data):
        # Process received data
    def send_data(self, message):
        # Reply to message etc
        self.transport.write(message)
factory = protocol.ServerFactory()
factory.protocol = FactoryProcess
reactor.listenTCP(8256,factory)
reactor.run()

机器可以连接并发送它们的数据,我可以在 send_data 块中发回确认。 到目前为止,一切都很好。 我无法理解如何从协议代码外部向其中一个设备异步发送数据。显然,我需要以某种方式访问​​ Factory class 的实例以获取我希望使用的特定连接,但我看不到如何访问。 保持安全,非常感谢。

编辑 在@notorious.no 提供了一个非常有用的示例之后,我更改了我的代码以捕获 IP 地址和端口,以及已连接设备的连接对象:

from twisted.internet import endpoints, protocol, reactor

device_ips = []
device_ports = []
connections = []

class ChatProtocol(protocol.Protocol):
    def connectionMade(self):
        global device_ips, device_ports, connections
        # Append client
        self.factory.clientList.append(self)
        print('client connected. Connection Count = ' + str(len(self.factory.clientList)))
        connections.append(self)
        ip, port = self.transport.client
        device_ips.append(ip)
        device_ports.append(port)
        print('ips:' + str(device_ips) + ', ports:' + str(device_ports) + ', connections:' + str(connections))


    def connectionLost(self, _):
        # Remove client
        self.factory.clientList.remove(self)
        print('client lost. Connection Count = ' + str(len(self.factory.clientList)))

    def dataReceived(self, data):
        print('Data received:' + str(data))
        # Send message to all connected clients
        for client in self.factory.clientList:
            if client == self:
                continue

            client.transport.write(data)

class ChatFactory(protocol.Factory):
    protocol = ChatProtocol
    clientList = []

def main():
    epServer = endpoints.serverFromString(reactor, "tcp:8123")
    epServer.listen(ChatFactory())
    reactor.run()

main()

当我 运行 然后连接两个测试设备时,我得到:

client connected. Connection Count = 1
ips:['redacted'], ports:[54182], connections:[<__main__.ChatProtocol instance at 0x7f5a835afcd0>]
client connected. Connection Count = 2
ips:['redacted', 'redacted'], ports:[54182, 57437], connections:[<__main__.ChatProtocol instance at 0x7f5a835afcd0>, <__main__.ChatProtocol instance at 0x7f5a835c2140>]

现在我有了已连接设备 IP 和端口的列表,大概我可以使用连接对象在需要时异步发送消息。请你告诉我该怎么做? 保持安全...

不太确定您所说的 "devices from outside the Protocol code" 是什么意思,但我假设您的意思是访问已连接到同一服务器的其他客户端(如果不是这种情况,请发表评论)。您可以做的一件事是在工厂对象中列出已连接的协议。 Factory.buildProtocol(默认情况下,除非您重载它)将在 protocol.

中设置 factory 参数
from twisted.internet import endpoints, protocol, reactor

class ChatProtocol(protocol.Protocol):
    def connectionMade(self):
        # Append client
        self.factory.clientList.append(self)
        print(len(self.factory.clientList))

    def connectionLost(self, _):
        # Remove client
        self.factory.clientList.remove(self)
        print(len(self.factory.clientList))

    def dataReceived(self, data):
        # Send message to all connected clients
        for client in self.factory.clientList:
            if client == self:
                continue

            client.transport.write(data)

class ChatFactory(protocol.Factory):
    protocol = ChatProtocol
    clientList = []

def main():
    epServer = endpoints.serverFromString(reactor, "tcp:8256:interface=0.0.0.0")
    epServer.listen(ChatFactory())
    reactor.run()

main()