2014-02-14 3 views
4

Я пытаюсь адаптировать Python Twisted - UDP examples для использования широковещательной передачи UDP. Я могу отправить сообщение от клиента и получить его на сервере, однако он не отправляет сообщение обратно.Twisted Python: UDP Broadcast (простой сервер эха)

Клиент:

from twisted.internet.protocol import DatagramProtocol 
from twisted.internet import reactor 

from socket import SOL_SOCKET, SO_BROADCAST 

class EchoClientDatagramProtocol(DatagramProtocol): 
    strings = [ 
     "Hello, world!", 
     "What a fine day it is.", 
     "Bye-bye!" 
    ] 

    def startProtocol(self): 
     self.transport.socket.setsockopt(SOL_SOCKET, SO_BROADCAST, True) 
     self.transport.connect("255.255.255.255", 8000) 
     self.sendDatagram() 

    def sendDatagram(self): 
     if len(self.strings): 
      datagram = self.strings.pop(0) 
      self.transport.write(datagram) 
     else: 
      reactor.stop() 

    def datagramReceived(self, datagram, host): 
     print 'Datagram received: ', repr(datagram) 
     self.sendDatagram() 

def main(): 
    protocol = EchoClientDatagramProtocol() 
    #0 means any port 
    t = reactor.listenUDP(0, protocol) 
    reactor.run() 

if __name__ == '__main__': 
    main() 

Сервер:

from twisted.internet.protocol import DatagramProtocol 
from twisted.internet import reactor 

class EchoUDP(DatagramProtocol): 
    def datagramReceived(self, datagram, address): 
     print "Received from address: " + str(address) 
     print str(datagram) 
     self.transport.write(datagram, address) 
     print "Finished sending reply." 

print "Starting server." 
reactor.listenUDP(8000, EchoUDP()) 
reactor.run() 

Консоль вывода:

Server: 

Starting server. 
Received from address ('192.168.1.137', 53737) 
Hello, world! 
Finished sending reply. 

Client: 

no output. 
+0

Возможно, вы имели в виду 'main', чтобы быть функцией внутри' EchoClientDatagramProtocol', или это проблема форматирования? – jozzas

+0

@jozzas: проблема с форматированием, мои извинения. Я редактировал приведенный выше код. – firefly2442

ответ

2

transport.connect создает connected UDP socket

Связанный разъем UDP немного отличается от стандартного - он может отправлять и принимать датаграммы только на/из одного адреса, но это никоим образом не подразумевает соединение. Дейтаграммы все равно могут поступать в любом порядке, и порт с другой стороны, возможно, никто не слушает. Преимущество подключенного сокета UDP заключается в том, что он может предоставлять уведомление о недоставленных пакетах. Это зависит от многих факторов, почти все из которых не подпадают под действие приложения, но оно все же дает определенные преимущества, которые изредка делают его полезным.

Я подозреваю, что ответ с сервера не был пойман клиентом, поскольку он прослушивает ответы от широковещательного адреса, а не конкретный адрес сервера.

Вместо этого используйте форму записи self.transport.write(data, (host, port)) без первоначального подключения - это позволит клиенту получать пакеты с любого адреса.

from twisted.internet.protocol import DatagramProtocol 
from twisted.internet import reactor 

from socket import SOL_SOCKET, SO_BROADCAST 

class EchoClientDatagramProtocol(DatagramProtocol): 
    strings = [ 
     "Hello, world!", 
     "What a fine day it is.", 
     "Bye-bye!" 
    ] 

    def startProtocol(self): 
     self.transport.socket.setsockopt(SOL_SOCKET, SO_BROADCAST, True) 
     #self.transport.connect("255.255.255.255", 8000) <- not needed 
     self.sendDatagram() 

    def sendDatagram(self): 
     if len(self.strings): 
      datagram = self.strings.pop(0) 
      self.transport.write(datagram, ('255.255.255.255', 8000)) # <- write to broadcast address here 
     else: 
      reactor.stop() 

    def datagramReceived(self, datagram, host): 
     print 'Datagram received: ', repr(datagram) 
     self.sendDatagram() 

def main(): 
    protocol = EchoClientDatagramProtocol() 
    #0 means any port 
    t = reactor.listenUDP(0, protocol) 
    reactor.run() 


if __name__ == '__main__': 
    main() 
Смежные вопросы