【发布时间】:2011-04-07 15:04:39
【问题描述】:
我想创建一个服务器和客户端,使用 Twisted 从网络发送和接收 UDP 数据包。我已经用 Python 中的套接字编写了这个,但想利用 Twisted 的回调和线程特性。但是,我需要 Twisted 设计方面的帮助。
我想要接收多种类型的数据包,但我们假设只有一种:
class Packet(object):
def __init__(self, data=None):
self.packet_type = 1
self.payload = ''
self.structure = '!H6s'
if data == None:
return
self.packet_type, self.payload = struct.unpack(self.structure, data)
def pack(self):
return struct.pack(self.structure, self.packet_type, self.payload)
def __str__(self):
return "Type: {0}\nPayload {1}\n\n".format(self.packet_type, self.payload)
我制作了一个协议类(几乎是示例的直接副本),当我从另一个程序发送数据时,它似乎可以工作:
class MyProtocol(DatagramProtocol):
def datagramReceived(self, data, (host, port)):
p = Packet(data)
print p
reactor.listenUDP(3000, MyProtocol())
reactor.run()
我不知道如何创建一个客户端,它可以在网络上发送任意数据包,这些数据包会被反应器接收:
# Something like this:
s = Sender()
p = Packet()
p.packet_type = 3
s.send(p.pack())
p.packet_type = 99
s.send(p.pack())
我还需要确保在客户端和服务器上设置重用地址标志,以便我可以在同一设备上同时运行每个的多个实例(例如,一个脚本正在发送心跳,另一个脚本响应心跳等)。
有人可以告诉我如何使用 Twisted 来实现吗?
更新:
这就是我在 Python 中使用套接字的方式。我可以同时运行多个侦听器和发送器,它们都可以互相听到。如何使用 Twisted 获得此结果? (收听部分不必是一个单独的过程。)
class Listener(Process):
def __init__(self, ip='127.0.0.1', port=3000):
Process.__init__(self)
self.ip = ip
self.port = port
def run(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((self.ip, self.port))
data, from_ip = sock.recvfrom(4096)
p = Packet(data)
print p
class Sender(object):
def __init__(self, ip='127.255.255.255', port=3000):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.ip = (ip, port)
def send(self, data):
self.sock.sendto(data, self.ip)
if __name__ == "__main__":
l = Listener()
l.start()
s = Sender()
p = Packet()
p.packet_type = 4
p.payload = 'jake'
s.send(p.pack())
工作解决方案:
class MySender(DatagramProtocol):
def __init__(self, packet, host='127.255.255.255', port=3000):
self.packet = packet.pack()
self.host = host
self.port = port
def startProtocol(self):
self.transport.write(self.packet, (self.host, self.port))
if __name__ == "__main__":
packet = Packet()
packet.packet_type = 1
packet.payload = 'jake'
s = MySender(packet)
reactor.listenMulticast(3000, MyProtocol(), listenMultiple=True)
reactor.listenMulticast(3000, s, listenMultiple=True)
reactor.callLater(4, reactor.stop)
reactor.run()
【问题讨论】: