def test_no_client_monitor(self): socket_address = "tcp://127.0.0.1:9999" no_clients_triggered = False # Increase the polling interval, to make tests faster. mflow.SocketEventListener.DEFAULT_SOCKET_RECEIVE_TIMEOUT = 0.01 def no_clients(): nonlocal no_clients_triggered no_clients_triggered = True server = mflow.connect(address=socket_address, conn_type=mflow.BIND, mode=mflow.PUSH, no_client_action=no_clients, no_client_timeout=0.3) self.assertFalse(no_clients_triggered, "Timeout triggered too fast.") time.sleep(0.2) self.assertFalse(no_clients_triggered, "Timeout triggered too fast.") time.sleep(0.3) self.assertTrue(no_clients_triggered, "Did not trigger timeout if no clients connected.") # Reset the test. no_clients_triggered = False # First client. client_1 = mflow.connect(socket_address) time.sleep(0.4) self.assertFalse(no_clients_triggered, "Callback triggered even with connected clients.") client_1.disconnect() # Wait a bit and verify the triggering status. time.sleep(0.1) self.assertFalse(no_clients_triggered, "Timeout triggered too fast.") time.sleep(0.3) self.assertTrue(no_clients_triggered, "Callback did not re-trigger.") server.disconnect()
def main(): import argparse import sys parser = argparse.ArgumentParser(description='Stream dump utility') parser.add_argument('-c', '--config', help='Configuration file') parser.add_argument( 'source', type=str, nargs='?', help='Source address - format "tcp://<address>:<port>"') parser.add_argument('streams', type=str, nargs='*', help='Streams to generate - "tcp://<address>:<port>"') arguments = parser.parse_args() if arguments.config: print('config') (input_stream, splitter) = load_configuration(arguments.config) elif arguments.source and arguments.streams: streams_to_generate = arguments.streams address = arguments.source output_streams = [] for new_stream in streams_to_generate: output_streams.append( mflow.connect(new_stream, conn_type=mflow.BIND, mode=mflow.PUSH)) splitter = Splitter(output_streams) input_stream = mflow.connect(address) else: parser.print_help() sys.exit(-1) # Info: By here splitter and input_stream needs to be specified # Signal handling global receive_more receive_more = True def stop(*arguments): global receive_more receive_more = False signal.siginterrupt() signal.signal(signal.SIGINT, stop) while receive_more: input_stream.receive(handler=splitter.receive)
def open(self, no_client_action=None, no_client_timeout=None): self.stream = mflow.connect('%s:%d' % (self.address, self.port), queue_size=self.queue_size, conn_type=self.conn_type, mode=self.mode, no_client_action=no_client_action, no_client_timeout=no_client_timeout, copy=self.copy, send_timeout=self.send_timeout) # Main header self.main_header = dict() self.main_header['htype'] = "bsr_m-1.1" if self.data_header_compression: self.main_header['dh_compression'] = self.data_header_compression # Data header with self.channels_lock: self._create_data_header() # Set initial pulse_id self.pulse_id = self.start_pulse_id # Update internal status self.status_stream_open = True
def main(): parser = argparse.ArgumentParser(description='Stream generation utility') parser.add_argument('-a', '--address', default="tcp://*:9999", type=str, help='Address - format "tcp://<address>:<port>"') parser.add_argument('-s', '--size', default=1, type=float, help='Size of data to send (MB)"') arguments = parser.parse_args() address = arguments.address size = arguments.size stream = mflow.connect(address, conn_type="bind", mode=mflow.PUSH) size_bytes = int(size*1024.0*1024.0) data = bytearray(size_bytes) # message_size_mb = (size*8)/1024.0/1024.0 print('Sending messages of size %f MB' % size) while True: # Sending random data # stream.send(os.urandom(size * 8), send_more=False) # Slow - cryptographically strong random numbers # stream.send(numpy.random.random(size), send_more=False) # Fast - random numbers stream.send(data, send_more=False)
def sender(address, n, q, block=True, copy=True): stream = mflow.connect(address, conn_type=mflow.BIND, mode=mflow.PUSH, queue_size=100, copy=copy) data = np.ones(10, dtype=np.int32) data_size = len(data.tobytes()) i = 0 total_size = 0 while i < n: try: header = {'htype': 'array-1.0', 'type': 'int32', 'shape': [10, ], 'frame': i} stream.send(json.dumps(header).encode('utf-8'), send_more=True, block=block) stream.send(data.tobytes(), block=block) i += 1 total_size += data_size total_size += len(json.dumps(header).encode('utf-8')) q.put({'bytes_sent': data_size, 'total_sent': total_size}) # Send out every 10ms time.sleep(0.01) except KeyboardInterrupt: break stream.disconnect() return
def main(): parser = argparse.ArgumentParser(description='Stream replay utility') parser.add_argument('folder', type=str, help='Destination folder') parser.add_argument('-a', '--address', default="tcp://*:9999", type=str, help='Address - format "tcp://<address>:<port>" (default: "tcp://*:9999")') arguments = parser.parse_args() folder = arguments.folder address = arguments.address if not os.path.exists(folder): os.makedirs(folder) stream = mflow.connect(address, conn_type="bind", mode=zmq.PUSH) files = sorted(listdir(folder)) for index, raw_file in enumerate(files): filename = join(folder, raw_file) if not (raw_file.endswith('.raw') and isfile(filename)): continue with open(filename, mode='rb') as file_handle: send_more = False if index+1 < len(files): # Ensure that we don't run out of bounds send_more = raw_file.split('_')[0] == files[index+1].split('_')[0] print('Sending %s [%s]' % (raw_file, send_more)) stream.send(file_handle.read(), send_more=send_more)
def receive(source, file_name, queue_size=100, mode=zmq.PULL, n_messages=None, message_processor=None): handler = extended.Handler() receiver = mflow.connect(source, conn_type="connect", queue_size=queue_size, mode=mode) if message_processor is None: message_processor = process_message writer = wr.Writer() writer.open_file(file_name) first_iteration = True if not n_messages: n_messages = -1 try: while n_messages != 0: success = message_processor(handler, receiver, writer, first_iteration) if success: first_iteration = False n_messages -= 1 finally: writer.close_file()
def main(): import time import argparse parser = argparse.ArgumentParser(description='Stream statistic utility') parser.add_argument('source', type=str, help='Source address - format "tcp://<address>:<port>"') arguments = parser.parse_args() address = arguments.source stream = mflow.connect(address) global messages_received global total_bytes_received global message_rate global receive_rate # Signal handling global more more = True def stop(*arguments): global more more = False print_statistics() signal.siginterrupt() signal.signal(signal.SIGINT, stop) previous_time = time.time() previous_total_bytes_received = 0 previous_messages_received = 0 while more: message = stream.receive(handler=dump) now = time.time() delta_time = now - previous_time # Print every second # TODO Need to be done differently as at the end of a stream the last stats do not show up # Use threading.Timer(1, foo).start() # (http://stackoverflow.com/questions/8600161/executing-periodic-actions-in-python) # As printing out every time a message is received will slow down the receive process # if delta_time > 0.1: if 1: total_bytes_received = message.statistics.total_bytes_received messages_received = message.statistics.messages_received receive_rate = (total_bytes_received - previous_total_bytes_received) / delta_time message_rate = (messages_received - previous_messages_received) / delta_time previous_total_bytes_received = total_bytes_received previous_messages_received = messages_received if delta_time > 0.1: previous_time = now print_statistics()
def connect(self): self.stream = mflow.connect(self.address, conn_type=self.conn_type, queue_size=self.queue_size, mode=self.mode, copy=self.copy, receive_timeout=self.receive_timeout) return self # Return self to be backward compatible
def main(): import argparse import sys parser = argparse.ArgumentParser(description="Stream dump utility") parser.add_argument("-c", "--config", help="Configuration file") parser.add_argument("source", type=str, nargs="?", help='Source address - format "tcp://<address>:<port>"') parser.add_argument("streams", type=str, nargs="*", help='Streams to generate - "tcp://<address>:<port>"') arguments = parser.parse_args() if arguments.config: print("config") (input_stream, splitter) = load_configuration(arguments.config) elif arguments.source and arguments.streams: streams_to_generate = arguments.streams address = arguments.source output_streams = [] for new_stream in streams_to_generate: output_streams.append(mflow.connect(new_stream, conn_type=mflow.BIND, mode=mflow.PUSH)) splitter = Splitter(output_streams) input_stream = mflow.connect(address) else: parser.print_help() sys.exit(-1) # Info: By here splitter and input_stream needs to be specified # Signal handling global receive_more receive_more = True def stop(*arguments): global receive_more receive_more = False signal.siginterrupt() signal.signal(signal.SIGINT, stop) while receive_more: input_stream.receive(handler=splitter.receive)
def main(): parser = argparse.ArgumentParser(description='Stream statistic utility') parser.add_argument( 'source', type=str, help='Source address - format "tcp://<address>:<port>"') parser.add_argument( '-m', '--mode', default='pull', choices=['pull', 'sub'], type=str, help='Communication mode - either pull (default) or sub') parser.add_argument( '-i', "--sampling_interval", type=float, default=0.5, help="Interval in seconds at which to sample the stream.\n" "If zero, every packet will be sampled.") arguments = parser.parse_args() address = arguments.source mode = mflow.SUB if arguments.mode == 'sub' else mflow.PULL stream = mflow.connect(address, mode=mode, receive_timeout=1000) statistics_printer = ThroughputStatisticsPrinter( sampling_interval=arguments.sampling_interval) def dump(receiver): """ Just read the stream. :param receiver: Function to use as a receiver. :return: 1 if the reception was successful, None if it timed out. """ data = receiver.next() while receiver.has_more(): # If any of the message parts time outed (the only way a message part can be None) if receiver.next() is None: return None # Return 1 only for valid data. return 1 if data else None print("mflow stats started. Sampling interval is %.2f seconds." % arguments.sampling_interval) print("_" * 60) try: while True: message = stream.receive(handler=dump) if message is not None: statistics_printer.save_statistics(message.statistics) except KeyboardInterrupt: stream.disconnect() # Flush and Print summary. statistics_printer.close()
def receiver(address, n, q, block=True, copy=True): stream = mflow.connect(address, conn_type=mflow.CONNECT, mode=mflow.PULL, queue_size=100, copy=copy) i = 0 while i < n: message = stream.receive(block=block) if message: if message.data is not None: if message.data["header"] is not None: i += 1 q.put({"total_sent": message.statistics.total_bytes_received, "stat": message.statistics.messages_received, "counter": i, }) #time.sleep(0.1) stream.disconnect() return
def main(): import argparse global counter global folder global skip_from_message parser = argparse.ArgumentParser(description='Stream dump utility') parser.add_argument('source', type=str, help='Source address - format "tcp://<address>:<port>"') parser.add_argument('folder', default=None, nargs='?', type=str, help='Destination folder') parser.add_argument('-m', '--mode', default='pull', type=str, help='Communication mode - either pull (default) or sub') parser.add_argument('-s', '--skip', default=None, type=int, help='Skip sub-messages starting from this number (including number)') arguments = parser.parse_args() folder = arguments.folder address = arguments.source skip_from_message = arguments.skip mode = mflow.SUB if arguments.mode == 'sub' else mflow.PULL if folder and not os.path.exists(folder): os.makedirs(folder) stream = mflow.connect(address, mode=mode) # Signal handling global receive_more receive_more = True def stop(*arguments): global receive_more receive_more = False signal.siginterrupt() signal.signal(signal.SIGINT, stop) # Select handler handler = dump if not folder: handler = dump_screen while receive_more: stream.receive(handler=handler) counter += 1
def main(): parser = argparse.ArgumentParser(description='Stream generation utility') parser.add_argument('-a', '--address', default="tcp://*:9999", type=str, help='Address - format "tcp://<address>:<port>"') parser.add_argument('-s', '--size', default=1, type=float, help='Size of data to send (MB)"') parser.add_argument('-m', '--mode', default='push', type=str, help='Communication mode - either push (default) or pub') arguments = parser.parse_args() address = arguments.address size = arguments.size mode = mflow.PUB if arguments.mode == 'pub' else mflow.PUSH stream = mflow.connect(address, conn_type="bind", mode=mode) size_bytes = int(size*1024.0*1024.0) header = {'htype': 'raw-1.0', 'type': 'int32', 'shape': [1, size_bytes/4]} data = bytearray(size_bytes) print('Sending messages of size %f MB' % size) statistics = ThroughputStatisticsPrinter() message_statistics = argparse.Namespace(total_bytes_received=0) counter = 0 try: while True: # Sending random data # stream.send(os.urandom(size * 8), send_more=False) # Slow - cryptographically strong random numbers # stream.send(numpy.random.random(size), send_more=False) # Fast - random numbers header["frame"] = counter stream.send(json.dumps(header).encode('utf-8'), send_more=True) stream.send(data, send_more=False) counter += 1 # Not totally correct - the total bytes do not take into account the header. message_statistics.total_bytes_received += size_bytes message_statistics.messages_received = counter statistics.save_statistics(message_statistics) except KeyboardInterrupt: print("Terminated by user.") statistics.close()
def reply_folder(bind_address, folder, mode): if not os.path.exists(folder): raise ValueError("Specified folder '%s' does not exist.") stream = mflow.connect(bind_address, conn_type="bind", mode=mode) files = sorted(listdir(folder)) for index, raw_file in enumerate(files): filename = join(folder, raw_file) if not (raw_file.endswith('.raw') and isfile(filename)): continue with open(filename, mode='rb') as file_handle: send_more = False if index + 1 < len( files): # Ensure that we don't run out of bounds send_more = raw_file.split('_')[0] == files[index + 1].split('_')[0] print('Sending %s [%s]' % (raw_file, send_more)) stream.send(file_handle.read(), send_more=send_more)
def receive(source=None, clear=False, queue_size=100, mode=zmq.PULL, channel_filter=None): numpy.set_printoptions(threshold=5) numpy.set_printoptions(linewidth=100) print('Trying to connect to %s' % source) receiver = mflow.connect(source, conn_type="connect", queue_size=queue_size, mode=mode) handler = Handler() while True: message = receiver.receive(handler=handler.receive) message = message.data # As the rest of the code is only interested in the message data, not statistics # if message_data['header']['pulse_id'] % 10 == 0: # sys.stderr.write("\x1b[2J\x1b[H") if clear: print((chr(27) + "[2J")) separator = '\t' # separator = ', ' if message.format_changed or clear: # Have pulse_id, ... in first column keys = "pulse_id" + separator + "global_timestamp" + separator + "global_timestamp_offset" for key in message.data.keys(): if channel_filter and key not in channel_filter: # continue with next element as this one is not in the filter list continue if keys: keys = keys + separator + key else: keys = key print(keys) # pprint.pprint(message.data.values()) # Have pulse_id in first column values = str(message.pulse_id) + separator + str( message.global_timestamp) + separator + str( message.global_timestamp_offset) for key in message.data.keys(): if channel_filter and key not in channel_filter: # continue with next element as this one is not in the filter list continue value = message.data[key] if values: values = values + separator + str(value.value) else: values = str(value.value) # for value in message.data.values(): # # if values: # values = values + separator + str(value.value) # else: # values = str(value.value) print(values)
import sys import os import logging try: import mflow except: sys.path.append(os.environ["PWD"] + "/../") import mflow logger = logging.getLogger("mflow.mflow") logger.setLevel(logging.DEBUG) address = "tcp://127.0.0.1:40000" stream = mflow.connect(address, conn_type=mflow.CONNECT, mode=mflow.PULL, receive_timeout=1, queue_size=1) for i in range(100): message = stream.receive() print(message.data) print(message.statistics.messages_received) stream.disconnect()
def load_configuration(filename): """ Read in a configuration file like this: { "source": { "address": "tcp://localhost:7777", "mode": "PULL", "queue_size": 100 }, "streams": [ { "address": "tcp://*:8888", "mode": "PUSH" } ] } """ import json import re # Load configuration file with open(filename) as file_handle: configuration = json.load(file_handle) # Construct stream source address = configuration["source"]["address"] if re.match("tcp://\\*:.*", address): connection_type = mflow.BIND else: connection_type = mflow.CONNECT mode = mflow.PULL if "mode" in configuration["source"]: if configuration["source"]["mode"].lower() == "pull": mode = mflow.PULL elif configuration["source"]["mode"].lower() == "sub": mode = mflow.SUB else: raise Exception( "Unsupported mode [%s] for source [%s]" % (configuration["source"]["mode"], configuration["source"]) ) queue_size = 100 if "queue_size" in configuration["source"]: queue_size = configuration["source"]["queue_size"] input_stream = mflow.connect(address, mode=mode, conn_type=connection_type, queue_size=queue_size) # Construct output streams output_streams = [] for stream in configuration["streams"]: address = stream["address"] if re.match("tcp://\\*:.*", address): connection_type = mflow.BIND else: connection_type = mflow.CONNECT mode = mflow.PUSH if "mode" in stream: if stream["mode"].lower() == "push": mode = mflow.PUSH elif stream["mode"].lower() == "pub": mode = mflow.PUB else: raise Exception("Unsupported mode [%s] for stream [%s]" % (stream["mode"], stream)) queue_size = 100 if "queue_size" in stream: queue_size = stream["queue_size"] output_streams.append(mflow.connect(address, conn_type=connection_type, mode=mode, queue_size=queue_size)) return input_stream, Splitter(output_streams)
def load_configuration(filename): """ Read in a configuration file like this: { "source": { "address": "tcp://localhost:7777", "mode": "PULL", "queue_size": 100 }, "streams": [ { "address": "tcp://*:8888", "mode": "PUSH" } ] } """ import json import re # Load configuration file with open(filename) as file_handle: configuration = json.load(file_handle) # Construct stream source address = configuration['source']['address'] if re.match('tcp://\\*:.*', address): connection_type = mflow.BIND else: connection_type = mflow.CONNECT mode = mflow.PULL if 'mode' in configuration['source']: if configuration['source']['mode'].lower() == 'pull': mode = mflow.PULL elif configuration['source']['mode'].lower() == 'sub': mode = mflow.SUB else: raise Exception( 'Unsupported mode [%s] for source [%s]' % (configuration['source']['mode'], configuration['source'])) queue_size = 100 if 'queue_size' in configuration['source']: queue_size = configuration['source']['queue_size'] input_stream = mflow.connect(address, mode=mode, conn_type=connection_type, queue_size=queue_size) # Construct output streams output_streams = [] output_filters = [] use_filter = False for stream in configuration['streams']: address = stream['address'] if re.match('tcp://\\*:.*', address): connection_type = mflow.BIND else: connection_type = mflow.CONNECT mode = mflow.PUSH if 'mode' in stream: if stream['mode'].lower() == 'push': mode = mflow.PUSH elif stream['mode'].lower() == 'pub': mode = mflow.PUB else: raise Exception('Unsupported mode [%s] for stream [%s]' % (stream['mode'], stream)) queue_size = 100 if 'queue_size' in stream: queue_size = stream['queue_size'] if 'modulo' in stream: output_filters.append(ModuloFilter(int(stream['modulo']))) use_filter = True else: output_filters.append(None) output_streams.append( mflow.connect(address, conn_type=connection_type, mode=mode, queue_size=queue_size)) if use_filter: return input_stream, FilterSplitter(output_streams, output_filters) else: return input_stream, Splitter(output_streams)
import mflow except: sys.path.append(os.environ["PWD"] + "/../") import mflow import logging import numpy as np logger = logging.getLogger("mflow.mflow") logger.setLevel(logging.ERROR) address = "tcp://127.0.0.1:40000" stream = mflow.connect(address, conn_type=mflow.BIND, mode=mflow.PUSH, receive_timeout=1, queue_size=1) for i in range(16): try: header = '{"htype": "array-1.0", "type": "int32", "shape": [10], "frame": %d}' % i data = np.zeros(10, dtype=np.int32) + i stream.send(header.encode(), send_more=True, block=True) stream.send(data.tobytes(), block=False) print("Sending message %d" % i) # Send out every 10ms time.sleep(0.01)
try: import mflow except: sys.path.append(os.environ["PWD"] + "/../") import mflow import logging import numpy as np logger = logging.getLogger("mflow.mflow") logger.setLevel(logging.DEBUG) address = "tcp://127.0.0.1:40000" stream = mflow.connect(address, conn_type=mflow.BIND, mode=mflow.PUSH, receive_timeout=1, queue_size=1) data = np.ones(10, dtype=np.int32) i = 0 while True: try: header = '{"htype": "array-1.0", "type": "int32", "shape": [10], "frame": %d}' % i stream.send(header.encode(), send_more=True, block=False) stream.send(data.tobytes(), block=False) i += 1 # Send out every 10ms time.sleep(0.01) except KeyboardInterrupt: break
def test_timeout(): socket_address = "tcp://127.0.0.1:9999" server = mflow.connect(address=socket_address, conn_type=mflow.BIND, mode=mflow.PUSH, send_timeout=send_timeout) server.send(message={"valid": True}, block=True, as_json=True)
def main(): # Argument parsing parser = argparse.ArgumentParser(description='bsread statistics utility') parser.add_argument( '-s', '--source', type=str, default=None, help='source address, has to be in format "tcp://<address>:<port>"') parser.add_argument( '-c', '--clear', action='count', help='Monitor mode / clear the screen on every message') parser.add_argument( '-m', '--mode', default='pull', choices=['pull', 'sub'], type=str, help= 'Communication mode - either pull or sub (default depends on the use of -s option)' ) parser.add_argument( '-n', default=1, type=int, help= 'Limit message printing to every n messages, this will reduce CPU load. Note that all ' 'messages are still received, but are not displayed. If -n 0 is passed message ' 'display is disabled') parser.add_argument( '-l', '--log', type=str, help= 'Enable logging. All errors (pulse_id skip, etc..) will be logged in file specified' ) parser.add_argument('-v', '--value', action='count', help='Display values') parser.add_argument('-q', '--queue', default=100, type=int, help='Queue size of incoming queue (default = 100)') parser.add_argument('channel', type=str, nargs='*', help='Channels to retrieve (from dispatching layer)') # Parse arguments arguments = parser.parse_args() address = arguments.source channels = arguments.channel clear = arguments.clear show_values = arguments.value show_nth_value = arguments.n logfile = arguments.log queue_size = arguments.queue use_dispatching = False mode = mflow.SUB if arguments.mode == 'sub' else mflow.PULL if not channels and not address: print('\nNo source nor channels are specified - exiting!\n') parser.print_help() exit(-1) if address: import re if not re.match('^tcp://', address): # print('Protocol not defined for address - Using tcp://') address = 'tcp://' + address if not re.match('.*:[0-9]+$', address): # print('Port not defined for address - Using 9999') address += ':9999' if not re.match('^tcp://[a-zA-Z.\-0-9]+:[0-9]+$', address): print('Invalid URI - ' + address) exit(-1) else: # Connect via the dispatching layer use_dispatching = True address = dispatcher.request_stream(channels) mode = mflow.SUB if logfile: handler = logging.FileHandler(logfile) handler.setLevel(logging.DEBUG) logger.addHandler(handler) logger.info("Connecting to {} type PULL".format(address)) receiver = mflow.connect(address, conn_type="connect", queue_size=queue_size, mode=mode) handler = Handler() logger.info("Connection opened") messages_received = 0 previous_messages_received = 0 statistics = Statistics() previous_time = time.time() previous_total_bytes_received = 0 try: while True: message = receiver.receive(handler=handler.receive) total_bytes_received = message.statistics.total_bytes_received # Check consistency data_consistency_check(message.data, statistics) if show_nth_value != 0 and (messages_received % show_nth_value) == 0: if clear: print(chr(27) + "[2J") if show_values: print_message_data(message.data) now = time.time() delta_time = now - previous_time # Calculations receive_rate = (total_bytes_received - previous_total_bytes_received) / delta_time message_rate = (messages_received - previous_messages_received) / delta_time previous_total_bytes_received = total_bytes_received previous_messages_received = messages_received previous_time = now print("_" * 80) print("Messages Received: {}".format(messages_received)) print("Message Rate: {} Hz".format(message_rate)) print("Data Received: {} Mb".format(total_bytes_received / 1024.0 / 1024.0)) print("Receive Rate: {} Mbps".format(receive_rate / 1024 / 1024 * 8)) print("Missed Pulse_IDs: {} ".format( statistics.missed_pulse_ids)) print("Duplicated Pulse_IDs: {} ".format( statistics.duplicated_pulse_ids)) print("Reverted Pulse_IDs: {} ".format( statistics.reverted_pulse_ids)) messages_received += 1 except KeyboardInterrupt: # KeyboardInterrupt is thrown if the receiving is terminated via ctrl+c # As we don't want to see a stacktrace then catch this exception pass finally: if use_dispatching: print('Closing stream') dispatcher.remove_stream(address)
import sys import os import logging try: import mflow except: sys.path.append(os.environ["PWD"] + "/../") import mflow logger = logging.getLogger("mflow.mflow") logger.setLevel(logging.ERROR) address = "tcp://127.0.0.1:40000" stream = mflow.connect(address, conn_type=mflow.CONNECT, mode=mflow.PULL, receive_timeout=1, queue_size=1) while True: message = stream.receive() if message: print("Received frame %d." % message.data["header"]["frame"]) print(message.data) print(message.statistics.messages_received) stream.disconnect()