使用 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()
我正在编写一个 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()