Basically, when we want to transmit data between networked processes, two options are available:
Because we are interested in minimizing the total latency as much as possible, we will use UDP.
socket
stuff in Python
In [92]:
import socket
LISTENING_PORT = 8001
class UDP_receiver():
# We use a context manager (https://docs.python.org/3/reference/datamodel.html#context-managers).
def __enter__(self):
'''Create an UDP socket and listen to it.'''
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print("socket created")
self.sock.bind(('', LISTENING_PORT))
print(f"listening at {self.sock.getsockname()} ... ")
return self
def receive(self):
'''Receive a datagram.'''
(message, from_addr) = self.sock.recvfrom(1024) # Blocking operation, 1024 is the maximum expected payload size.
print(f"received {message} from {from_addr}")
return message
def __exit__(self,ext_type,exc_value,traceback):
'''Close the socket.'''
self.sock.close()
print("socket closed")
class UDP_sender():
def __enter__(self):
'''Create an UDP socket.'''
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print("socket created")
return self
def send(self, message, destination):
'''Send data.'''
self.sock.sendto(message, destination)
print(f"message {message} sent to destination {destination}")
def __exit__(self,ext_type,exc_value,traceback):
'''Close the socket.'''
self.sock.close()
print("socket closed")
def wait_for_a_message():
with UDP_receiver() as receiver:
message = receiver.receive().decode("utf-8")
print(f"recived message = {message}")
def send_message():
with UDP_sender() as sender:
message = b"hello world!"
destination = ('localhost', LISTENING_PORT)
sender.send(message, destination)
import threading
threading.Thread(target=wait_for_a_message).start()
send_message()
Notice that UDP is a datagram (independent packet) oriented protocol. The maximum packet size in UDP is 64 KB.