代码之家  ›  专栏  ›  技术社区  ›  paprika

Twisted:出站连接的源IP地址

  •  3
  • paprika  · 技术社区  · 15 年前

    我正在实现一个服务——用带有扭曲框架的python编写,在debian gnu/linux上运行——来检查SIP服务器的可用性。为此,我使用选项方法(SIP协议特性),因为这似乎是一个常见的实践。为了构造正确且符合RFC的报头,我需要知道要建立的连接的源IP地址和源端口。[如何]这可以通过扭曲来完成吗?

    这就是我所尝试的: I子类 protocol.DatagramProtocol startProtocol(self) 我用过 self.transport.getHost().host self.transport.getHost().port . 后者确实是将要使用的端口,而前者只生成0.0.0.0。

    我想在这一点上扭曲还没有?]知道将使用哪个接口以及哪个源IP地址。Twisted是否提供了一个可以帮助我实现这一点的设施,或者我是否需要以不同的方式与OS(路由)接口?或者我只是用了 self.transport.gethost().host 不正确?

    3 回复  |  直到 15 年前
        1
  •  8
  •   paprika    15 年前

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

    在尝试确定主机的源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
    
        2
  •  0
  •   Community CDub    7 年前

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

    1. 打电话 bind() 在套接字上并显式地给它一个地址
    2. 发送数据包

    如果你想了解更多细节, check this response .

    问题是我不太熟悉Twisted。从我对来源的快速了解可以看出,你可能想使用一个类似反应堆的 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() 你已经准备好了。

    现在最困难的部分是在扭曲提供的抽象的范围内完成这项工作。不幸的是,我在那里帮不了大忙。我建议您寻找一些关于如何访问底层套接字的示例,或者找到一种将套接字信息传递到框架中的方法。

    祝你好运。

        3
  •  0
  •   Tuure Laurinolli    15 年前

    您看到了是否可以使用Twisted的sip实现来实现您想要做的事情吗?

    在任何情况下,在Twisted中为UDP设置源地址和端口的方式都与在没有Twisted的情况下设置源地址和端口的方式非常相似。扭曲的, reactor.listenUDP(port, protocol, interface) 将一个UDP套接字绑定到一个特定的端口和接口,并将接收到的数据报处理到您的协议。在协议中, self.transport.write(msg, addr) 将数据报发送到 addr 使用协议绑定到的地址作为源地址。

    再读一遍你的问题,我想你唯一缺少的就是通过了 interface reactor.listenUDP(...) .