我正在实施一项服务 - 使用Twisted框架在Python上编写,在Debian GNU / Linux上运行 - 检查SIP服务器的可用性。为此,我使用OPTIONS方法(SIP协议功能),因为这似乎是一种常见的做法。为了构造正确且符合RFC的头,我需要知道将要建立的连接的源IP地址和源端口。 [怎么]可以用Twisted来完成?
这是我试过的:
我将protocol.DatagramProtocol子类化,在startProtocol(self)
内我使用了self.transport.getHost().host
和self.transport.getHost().port
。后者确实是将要使用的端口,而前者仅产生0.0.0.0。
我想在这一点上,Twisted不会[但是?]知道哪个接口以及将使用哪个源IP地址。 Twisted是否提供了可以帮助我解决这个问题的工具,还是需要以不同的方式与操作系统(路由)连接?或者我只是错误地使用self.transport.getHost().host
?
答案 0 :(得分: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
答案 1 :(得分:0)
如果您使用UDP,则端点由以下两者确定:
bind()
并明确地给它一个地址如果您想了解更多详情,请check this response。
问题是我不熟悉扭曲。通过快速浏览源代码,我看起来可能想要使用像t.i.d.SelectReactor
这样的反应器。这就是t.n.d.DNSDatagramProtocol
does under the hood。
如果您从图片中取出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()
并设置。
现在困难的部分是在扭曲提供的抽象范围内这样做。不幸的是,我在那里帮不了多少。我建议您查看有关如何访问底层套接字或找到将套接字信息传递到框架的方法的示例。
祝你好运。答案 2 :(得分:0)
您是否看到了Twisted的SIP实现是否可以实现?
在任何情况下,如何在Twisted中设置UDP的源地址和端口与在没有Twisted的情况下设置它们的方式非常相似。在Twisted中,reactor.listenUDP(port, protocol, interface)
将UDP套接字绑定到特定端口和接口,并将接收到的数据报处理到您的协议。在协议内部,self.transport.write(msg, addr)
使用协议绑定的地址作为源地址向addr
发送数据报。
再次阅读您的问题,我认为您遗失的唯一部分是将interface
传递给reactor.listenUDP(...)
。