通过UDP回送通过不同TCP端口回收的消息

时间:2015-05-05 00:33:12

标签: python sockets networking udp twisted

我使用Python 2.7.x(2.7.8)并尝试使用twisted python编写程序,其功能如下:

  • 程序等待通过TCP 7001或UDP 7000收到的消息。
  • 通过UDP 7000接收的消息将桥接到TCP 7001出去。

我无法弄清楚如何将UDP桥接到TCP,所以我在这个网站上查找了一个例子,就像这个,Twisted UDP to TCP Bridge,但问题是这个例子因为它不起作用而撒谎。我在datagramReceived上添加了一个“打印数据报”,以查看UDP是否响应接收任何内容,而不是。这完全令人沮丧。

这是我当前的测试代码从该示例改为一点

from twisted.internet.protocol import Protocol, Factory, DatagramProtocol
from twisted.internet import reactor

class TCPServer(Protocol):
    def connectionMade(self):
        self.port = reactor.listenUDP(7000, UDPServer(self))

    def connectionLost(self, reason):
        self.port.stopListening()

    def dataReceived(self, data):
        print "Server said:", data


class UDPServer(DatagramProtocol):
    def __init__(self, stream):
        self.stream = stream

    def datagramReceived(self, datagram, address):
        print datagram
        self.stream.transport.write(datagram)


def main():
    f = Factory()
    f.protocol = TCPServer
    reactor.listenTCP(7001, f)
    reactor.run()

if __name__ == '__main__':
    main()

正如您所看到的,我更改了端口以符合我的测试环境并添加了打印数据报以查看是否有任何调用datagramReceived。我将TCP内容发送到此程序没有问题,TCPServer工作正常,因为可以调用dataReceived。

1 个答案:

答案 0 :(得分:0)

以下是使用circuits应用程序框架的解决方案:

<强>代码:

#!/usr/bin/env python


from circuits.net.events import write
from circuits import handler, Component, Debugger
from circuits.net.sockets import TCPServer, UDPServer


class UDPTCPBroadcaster(Component):

    def init(self):
        self.clients = {}
        self.tcp = TCPServer(("0.0.0.0", 7001), channel="tcp").register(self)
        self.udp = UDPServer(("0.0.0.0", 7000), channel="udp").register(self)

    def broadcast(self, data, exclude=None):
        exclude = exclude or []
        targets = (sock for sock in self.clients.keys() if sock not in exclude)
        for target in targets:
            self.fire(write(target, data), "tcp")

    @handler("connect", channel="tcp")
    def _on_tcp_connect(self, sock, host, port):
        self.clients[sock] = {"host": sock, "port": port}

    @handler("disconnect", channel="tcp")
    def _on_tcp_disconnect(self, sock):
        if sock not in self.clients:
            return

        del self.clients[sock]

    @handler("read", channel="tcp")
    def _on_tcp_read(self, sock, data):
        data = data.strip().decode("utf-8")

        print sock, data

    @handler("read", channel="udp")
    def _on_udp_read(self, peer, data):
        # Broadcast to all connected TCP clients
        self.broadcast(data)


app = UDPTCPBroadcaster()
Debugger().register(app)
app.run()

这正是你所追求的,这里是测试结果......

终端#1 正在运行udptcpbroadcast.py

$ ./udptcpbroadcast.py 
<registered[tcp] (<TCPServer/tcp 31492:MainThread (queued=0) [S]>, <UDPTCPBroadcaster/* 31492:MainThread (queued=4) [R]> )>
<registered[udp] (<UDPServer/udp 31492:MainThread (queued=0) [S]>, <UDPTCPBroadcaster/* 31492:MainThread (queued=5) [R]> )>
<registered[*] (<Debugger/* 31492:MainThread (queued=0) [S]>, <UDPTCPBroadcaster/* 31492:MainThread (queued=5) [R]> )>
<started[*] (<UDPTCPBroadcaster/* 31492:MainThread (queued=4) [R]> )>
<registered[select] (<Select/select 31492:MainThread (queued=0) [S]>, <TCPServer/tcp 31492:MainThread (queued=0) [S]> )>
<ready[tcp] (<TCPServer/tcp 31492:MainThread (queued=0) [S]>, ('0.0.0.0', 7001) )>
<ready[udp] (<UDPServer/udp 31492:MainThread (queued=0) [S]>, ('0.0.0.0', 7000) )>
<_read[udp] (<socket._socketobject object at 0x7f5645168c20> )>
<read[udp] (('10.0.0.2', 35718), '\x00' )>
<_read[tcp] (<socket._socketobject object at 0x7f5645168bb0> )>
<connect[tcp] (<socket._socketobject object at 0x7f5645168c90>, '127.0.0.1', 57282 )>
<_read[udp] (<socket._socketobject object at 0x7f5645168c20> )>
<read[udp] (('10.0.0.2', 35718), 'Hello\n' )>
<write[tcp] (<socket._socketobject object at 0x7f5645168c90>, 'Hello\n' )>
<_write[tcp] (<socket._socketobject object at 0x7f5645168c90> )>
^C<signal[*] (2, <frame object at 0x1c38120> )>
<stopped[*] (<UDPTCPBroadcaster/* 31492:MainThread (queued=0) [S]> )>
<close[udp] ( )>
<close[tcp] ( )>
<closed[udp] ( )>
<disconnect[udp] (<socket._socketobject object at 0x7f5645168c20> )>
<disconnect[tcp] (<socket._socketobject object at 0x7f5645168bb0> )>
<disconnect[tcp] (<socket._socketobject object at 0x7f5645168c90> )>
<closed[tcp] ( )>

终端#2 发送UDP消息:

$ ./telnet.py -u localhost 7000
Trying localhost ...
Hello
^C

终端#3 接收广播UDP消息:

$ telnet localhost 7001
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello
Connection closed by foreign host.

请注意:这是有偏见的答案/解决方案。我是电路的作者:)也许来自Twisted Community的某人可以用 Twisted 版本做出回应进行比较! - 请注意./telnet.py工具直接来自circuits examples,是一个类似telnet的克隆,支持TCP和UDP。

更新:如果您不想“广播”到侦听TCP服务器上的每个连接的客户端,您可以更改此行为以定位特定的已连接客户端 - 但这取决于您你是如何做到这一点并进行管理的。 (哪个客户,我们如何定位他们等等)。