2014-02-14 44 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()