3

我正在实施一项服务——用 Python 编写,使用 Twisted 框架,在 Debian GNU/Linux 上运行——检查 SIP 服务器的可用性。为此,我使用 OPTIONS 方法(一种 SIP 协议功能),因为这似乎是一种司空见惯的做法。为了构造正确且符合 RFC 的标头,我需要知道要建立的连接的源 IP 地址和源端口。[如何] 使用 Twisted 可以做到这一点?

这就是我尝试过的:我将protocol.DatagramProtocol子类化并在其中startProtocol(self)使用self.transport.getHost().hostand self.transport.getHost().port。后者确实是要使用的端口,而前者只产生 0.0.0.0。

我想此时 Twisted [还没有?] 知道将使用哪个接口以及哪个源 IP 地址。Twisted 是否提供了可以帮助我解决此问题的工具,还是我需要以不同的方式与操作系统(路由)交互?还是我使用self.transport.getHost().host不当?

4

3 回答 3

8

为了完整起见,我回答我自己的问题:

在尝试确定主机的源 IP 地址之前,请确保在传输上使用 connect()。以下摘录显示了协议实现的相关部分:

class FooBarProtocol(protocol.DatagramProtocol):
    def startProtocol(self):
        self.transport.getHost().host   # => 0.0.0.0
        self.transport.connect(self.dstHost, self.dstPort)
        self.transport.getHost().host   # => 192.168.1.102
于 2009-11-18T18:46:04.420 回答
0

如果您使用的是 UDP,则端点由以下任一决定:

  1. 调用bind()套接字并明确地给它一个地址
  2. 发送数据包

如果您想了解更多详细信息,请查看此回复

问题是我对twisted不太熟悉。从我可以通过快速阅读来源得知,看起来您可能想要使用类似的反应器t.i.d.SelectReactor。这就是t.n.d.DNSDatagramProtocol幕后的工作

如果您twisted从图片中取出,则以下代码段显示了正在发生的事情:

>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
<socket._socketobject object at 0x10025d670>
>>> s.getsockname()           # this is an unbound or unnamed socket
('0.0.0.0', 0)
>>> s.bind( ('0.0.0.0', 0) )  # 0.0.0.0 is INADDR_ANY, 0 means pick a port
>>> s.getsockname()           # IP is still zero, but it has picked a port
('0.0.0.0', 56814)

如果您需要支持多个网络接口或 IPv4 和 IPv6,获取主机名会有点棘手。如果您可以使使用的接口可配置,则将其作为元组的第一个成员传递给您,socket.bind()然后您就可以设置了。

现在,困难的部分是在 twisted 提供的抽象范围内执行此操作。不幸的是,我在那里无能为力。我建议寻找有关如何访问底层套接字或找到将套接字信息传递到框架的方法的示例。

祝你好运。

于 2009-10-26T04:32:01.150 回答
0

您是否看到作为 Twisted 一部分的 SIP 实现是否可以实现您想要做的事情?

无论如何,在 Twisted 中为 UDP 设置源地址和端口的方式与在没有 Twisted 时设置它们的方式非常相似。在 Twisted 中,reactor.listenUDP(port, protocol, interface)将 UDP 套接字绑定到特定端口和接口,并将接收到的数据报处理到您的协议。在协议内部,使用协议绑定的地址作为源地址self.transport.write(msg, addr)发送数据报。addr

再次阅读您的问题,我认为您唯一缺少的部分是传递interfacereactor.listenUDP(...).

于 2009-11-01T13:51:09.173 回答