syntheso
syntheso

Reputation: 447

Receiving integers via UDP in Python

I am receiving data from an external program (Max/MSP) over UDP.

The data is coming into Python fine.

Strings come in as expected. i.e if I send "89-90-10-10" it comes in as a string that I can use in Python.

However, if I send a single integer, it comes in as "int�,i�����" despite using the decode() method.

What is going wrong in my code?

import socket

UDP_IP_ADDRESS = "127.0.0.1"

UDP_PORT_NO = 8813
serverSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverSock.bind((UDP_IP_ADDRESS, UDP_PORT_NO))


while True:
    print (type(data))
    print (repr(data))
    print (data.decode("utf-8"))

If I send "1" over udp from my other programme, I receive the following output in Python:

b'int\x00,i\x00\x00\x00\x00\x00\x01'

int,i

Upvotes: 1

Views: 1889

Answers (1)

Greg Mueller
Greg Mueller

Reputation: 526

The issue is that UDP stream is receiving bytes, regardless of whether you send a string or integer. So the program is likely packing the integer into bytes.

The code below is a hack that is ignoring some of the data received.
When you send an integer of 1 and receive b'int\x00,i\x00\x00\x00\x00\x00\x01' the "int" is telling the receiver that this is an integer. This is followed by nine bytes, where-as integers are usually sent in 1, 2, 4, or 8 bytes.
Using the last 8 bytes does not return the value 1, but using the last four bytes does, so the code below is slicing the bytes[-4:] to get only the last four.

There is probably some documentation or open source project that properly handles Max/MSP data so I suggest looking into that.

Here is the docs for the struct import that is used to unpack the data: https://docs.python.org/3/library/struct.html

import socket
import struct

UDP_IP_ADDRESS = "127.0.0.1"

UDP_PORT_NO = 8813
serverSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverSock.bind((UDP_IP_ADDRESS, UDP_PORT_NO))

while True:
    data, addr = serverSock.recvfrom(65536)
    if data.startswith(b'int'):
        # assumes 4 byte unsigned integer
        received = struct.unpack('!I', data[-4:])[0]
    else:
        received = data.decode('utf-8')
    print (repr(data))  # for debug purposes
    print (type(received), received)

Upvotes: 2

Related Questions