2014-02-14 67 views
4

我試圖修改Python Twisted-UDP examples以使用UDP廣播。我可以從客戶端發送消息並在服務器上接收消息,但是它不會發送消息。扭曲的Python:UDP廣播(簡單回聲服務器)

客戶:

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