2015-05-05 8 views
5

używam Python 2.7.x (2.7.8) i próbuję napisać program, za pomocą skręconych pytona funkcjonować tak:komunikaty echa otrzymane przez UDP z powrotem za pośrednictwem innego portu TCP

  • Program czeka dla komunikaty odebrane przez TCP 7001 lub UDP 7000.
  • Wiadomości odbierane przez UDP 7000 są łączone do wyjścia TCP 7001.

Nie mogłem dowiedzieć się, jak zlikwidować UDP TCP, więc spojrzał przykład na tej stronie, jak ten, Twisted UDP to TCP Bridge ale problemem jest to, że przykład kłamie, ponieważ nie działa. Dodałem "datagram drukowania" na datagramieReceived, aby sprawdzić, czy UDP odpowiada na otrzymanie niczego w ogóle i tak nie jest. To całkowicie frustrujące.

Oto mój aktualny kod testu zmieniane trochę z tego przykładu:

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()

Jak widać zmieniłem porty w celu dostosowania się moim środowisku testowym i dodano wydruk datagram, aby sprawdzić, czy nic nie wywołuje datagramu. Nie mam problemów z wysyłaniem rzeczy TCP do tego programu, TCPServer działa dobrze, ponieważ można wywołać metodę dataReceived.

+0

jest idea tutaj że przychodzące wiadomości na '' UDP/7000'' są kierowane do połączonych klientów na serwerze odsłuchu związany 'TCP/700''? –

+0

Czy to ma znaczenie, gdy porty są różne? Tak, właśnie to próbuję zrobić. Miałem wrażenie, że zrobiło to przykładowe łącze "Bridging UDP to TCP". –

+1

Jestem deweloperem [układy] (https://pypi.python.org/pypi/circuits) i tutaj jest to, co może * * praca: https://gist.github.com/prologic/ae987fe4f6fbbd9ca415 - I jeszcze tego nie testowałem :) –

Odpowiedz

0

Oto rozwiązanie przy użyciu circuits Application Framework:

Kod:

#!/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() 

To robi dokładnie to, co jesteś po i oto wyniki testu ...

Terminal # 1 Running 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] ()> 

Terminal nr 2 wysyłając komunikat UDP:

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

Terminal nr 3 otrzymaniu wiadomości transmisji UDP:

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

Uwaga: To stronniczy odpowiedź/rozwiązanie. Jestem autorką obwodów :) Być może jeśli ktoś z Twisted Community może odpowiedzieć wersją skręconą dla porównania! - Należy również zauważyć, że narzędzie ./telnet.py pochodzi bezpośrednio z circuits examples i jest klonem podobnym do telnetu z obsługą zarówno TCP, jak i UDP.

Aktualizacja: W przypadku, gdy nie chcesz „broadcast” do każdego podłączonego klienta na serwerze słuchania TCP można zmienić to zachowanie do ściśle określonych klientów podłączonych - Ale to zależy od Ciebie, jak to zrobić i zarządzaj nim. (którego klienta, w jaki sposób możemy na nie kierować itp.).

+0

Sądzę, że to naprawdę nie odpowiada na pytanie jako takie; ale jest to alternatywna implementacja, która spełnia te same wymagania :) Dzięki @ Jean-Paul Calderone –

+0

Naprawdę zamierzamy głosować na doskonale działającą alternatywną implementację problemu? –

3

Pobiegłem kod z pytaniem (z jednej niewielkiej modyfikacji: I włączone rejestrowanie). Kiedyś telnet aby połączyć się z serwerem TCP na porcie 7001. użyłem Pythona rEPL do utworzenia gniazda UDP i wysłać kilka datagramów do portu 7000.

Oto moja REPL zapis:

>>> import socket 
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
>>> s.sendto('hello', ('127.0.0.1', 7000)) 
5 
>>> s.sendto('world', ('127.0.0.1', 7000)) 
5 
>>> 

Oto mój dziennik serwera (sformatowane aby zmieścić się na ekranie):

... Log opened. 
... Factory starting on 7001 
... Starting factory <twisted.internet.protocol.Factory instance at 0x2b9b128> 
... UDPServer starting on 7000 
... Starting protocol <__main__.UDPServer instance at 0x2e8f8c0> 
... hello 
... world 

A oto moja sesja telnet zapis:

$ telnet localhost 7001 
Trying 127.0.0.1... 
Connected to localhost. 
Escape character is '^]'. 
helloworld 

Moja interpretacja tych wyników jest taka, że ​​program faktycznie działa tak, jak określono. Zastanawiam się, co robiłeś inaczej, gdy próbowałeś, co dawało inne, niepracujące wyniki.

Powiązane problemy