As one knows, God helps them that help themselves :) I found the solution to the subj problem. In order for broadcaster to receive responses, broadcaster must bind it's socket not to broadcast address, but to either it's own address (e.g. 192.168.2.1) or to empty string (which means "bind to all local addresses"). So the problem was not with Twisted but with my lack of knowledge in the area of networking :)
 
-- 
Kind regards, Roman Mescheryakov
 
 
17.04.2017, 21:58, "Роман Мещеряков" <romanmescheryakov@yandex.ru>:
Hi all,
 

After reading the UDP Networking how-to I added interaction using UDP messages to my distributed application. One sub-application is UDP broadcaster and the other one is responder.

Their minimized code is below:

 

broadcaster.py:

from datetime import datetime

import socket

import traceback

 

from twisted.internet import task, reactor

from twisted.internet.protocol import DatagramProtocol

 

DEFAULT_PORT = 2017

DEFAULT_HOST = "192.168.2.255"

DEFAULT_INTERVAL_SECONDS = 1

 

class BroadcasterProtocol(DatagramProtocol):

   def __init__(self, port):

       self._port = port

 

   def startProtocol(self):

       print "BroadcasterProtocol::startProtocol"

       self.transport.setBroadcastAllowed(True)

 

   def broadcastTime(self):

       time_str = datetime.now().time().strftime("%H:%M:%S.%f")

       try:

           self.transport.write(time_str.encode('utf-8'), ('<broadcast>', self._port))

           print "BroadcasterProtocol: broadcasted time: {}".format(time_str)

       except Exception:

           print "BroadcasterProtocol: time sending failed!"

 

   def datagramReceived(self, datagram, addr):

       print "BroadcasterProtocol: datagram from {} received:\n{}".format(addr, datagram)

 

def loopDone(unused):

   print "Loop done"

 

def loopFailure(failure):

   print "Loop failure! Failure is {}".format(traceback.format_exc(failure))

   

protocol = BroadcasterProtocol(DEFAULT_PORT)

the_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)

the_socket.setblocking(False)

the_socket.bind((DEFAULT_HOST, DEFAULT_PORT))

twisted_port = reactor.adoptDatagramPort(the_socket.fileno(), socket.AF_INET, protocol)

loop = task.LoopingCall(protocol.broadcastTime)

d = loop.start(DEFAULT_INTERVAL_SECONDS)

d.addCallback(loopDone).addErrback(loopFailure)

reactor.run()

 

responder.py:

from twisted.internet import reactor

from twisted.internet.protocol import DatagramProtocol

 

DEFAULT_PORT = 2017

 

class ResponderProtocol(DatagramProtocol):

   def datagramReceived(self, data, addr):

       print "ResponderProtocol: received from {addr}:\n{data}".format(

           addr = addr, data = data)

       response = "GOT " + data

       print "ResponderProtocol: sending response \"{response}\" to address {addr}".format(

           response = response, addr = addr)

       self.transport.write(response, addr)

 

responder_port = reactor.listenUDP(DEFAULT_PORT, ResponderProtocol())

reactor.run()

 

There are some reasons why I implemented UDP broadcasting and responding in the way that is a bit different than that shown in the official udpbroadcast.py example, but after reading UDP Networking how-to I thought this isn’t important.

ResponderProtocol.datagramReceived is successfully called with messages sent by broadcaster. Also I expected BroadcasterProtocol.datagramReceived to be called with “GOT <time>” responses sent by ResponderProtocol, but this doesn’t take place. Using strace I can see that sendto system function is being called by the responder process with “GOT <time>” messages, but there are no corresponding recv* calls in the broadcaster process.

Is this a bug or I made something wrong?

 
-- 
Kind regards, Roman Mescheryakov
 
,

_______________________________________________
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python