Sending numbers from Pure Data - numbers adding up instead of staying separate

80 Views Asked by At

I've got a very simple set up in Pure Data: it creates a local host socket and sends a number through this socket. The number comes either from a Vslider or a Number box.

Pure Data

This data is then received in Python through the Socket module. It is decoded and converted to float(), thereafter the float value is printed.

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 13001)
sock.bind(server_address)
sock.listen(1)

while True:
    connection, client_address = sock.accept()

    try:
        while True:
            data = connection.recv(16)
            data = data.decode("utf-8")
            data = data.replace('\n', '').replace('\t', '').replace('\r', '').replace(';', '')
            VARIABLE = float(data)
            print(f'received {VARIABLE} as a float')
    finally:
        connection.close()

The problem is that when I move the Vslider too quickly (or when I move the mouse cursor in the number box too quickly). The number values sent from Pd are "appended" together. For instance, I go very quickly from 1 to 10. Values 1-6 are correctly decoded and printed. However, values 7-10 are not printed separately, instead being printed as 78910. This can happen with any values up to 10 numbers or so. So I could get 12345678910111213 and so on. I'm fairly new to Pd so I'm not sure at all where this error originated.

python output

1

There are 1 best solutions below

0
umläute On

there are two (related) problems:

  1. TCP/IP is a serial protocol. there is no guarantee whatsoever that data sent in one go, will appear on the other side as a single "packet" (there is no notion of "packets" in TCP/IP). this means that it is possible that your code receives a single message in multiple connection.recv() invocations, or vice versa. you should therefore reassemble the buffers before processing them.
  2. Pd uses FUDI as the native application layer protocol, which uses the semicolon (;) as the delimiter between messages (so it is possible to reconstruct the various messages from the TCP/IP data stream). you are just throwing away this delimiter, rather than use it.

so there are two fixes to your problem:

  1. do not limit the receiving buffer to 16 bytes. just ask for much more, and you can usually ignore segmentation.
  2. split the received data at the ;

like this:

        while True:
            # receive a large buffer
            data = connection.recv(65535)
            data = data.decode("utf-8")
            # split a message boundaries
            for d in data.split(";"):
                # ignore line-feeds and the like
                d = d.strip()
                if not d:
                    continue
                VARIABLE = float(d)
                print(f"received {VARIABLE} as a float")