1

I stumbled upon some code in the book PyMOTW3 (https://pymotw.com/3/socket/multicast.html) and I could not understand why the time to live(ttl) argument was packed as struct.pack('b',1).

I tried searching the manuals to see if the arguments are supposed to be packed but it states that it can be integers. I tried inputting a normal integer and it seemed to work fine. It gave the same output as the code below. Then is there a specific reason why it has been packed like this ? I do know that packing it as 1 is unnecessary because the default value is 1, but what if I need to use some other number. Do I need to pack it?

I have included the code from the book below.

import socket
import struct
import sys

message = b'very important data'
multicast_group = ('224.3.29.71', 10000)

# Create the datagram socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Set a timeout so the socket does not block
# indefinitely when trying to receive data.
sock.settimeout(0.2)

# Set the time-to-live for messages to 1 so they do not
# go past the local network segment.
ttl = struct.pack('b', 1)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
print(s.getsockopt(socket.IPPROTO_IP,socket.IP_MULTICAST_TTL))

try:

    # Send data to the multicast group
    print('sending {!r}'.format(message))
    sent = sock.sendto(message, multicast_group)

    # Look for responses from all recipients
    while True:
        print('waiting to receive')
        try:
            data, server = sock.recvfrom(16)
        except socket.timeout:
            print('timed out, no more responses')
            break
        else:
            print('received {!r} from {}'.format(
                data, server))

finally:
    print('closing socket')
    sock.close()

This is the output I get whether I pack it or use a normal integer.

1

Sending very important message

Timed Out!

Closing Socket

Community
  • 1
  • 1
DJay
  • 25
  • 1
  • 5

1 Answers1

-2

All packets consist of bytes.

For the AF_INET or an IPv4 you can see the distribution of bits among the properties of the packet in this picture. You can see in the IPv4 header, TTL is the 9th octet of 20. TTL is an 8-bit (1-byte) field and can be from 0 to 255.

That is, each property should take a certain number of bits.

For this purpose, Python 3.7 has a module struct. This module performs conversions between Python values and C structs represented as Python bytes objects.

Since TTL is a positive integer of 1 byte in size, we have to select the unsigned char type, which is 'B'.

And so now the code looks like this:

ttl = struct.pack('B', 25)  # unsigned char as 1-byte object
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
afaikiac
  • 1
  • 1