UDP python sockets programming
-
Back-End
Simple client - server
After binding a port number to server listening socket, udp protocol allow the client to use two types of commands for sending / receiving data to / from server:
- using sendto-recvfrom
- using connect + send-recv
For udp data packet transmitted, there is no (built in) way to verify if this reached the destination, except we design a procedure of response confirmation from the server side.
#udp_server.py
import socket
MAX = 1024
ADDR = '' #all local interfaces
PORT = 1060
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((ADDR, PORT))
print (s.getsockname(), "is waiting ...")
while True:
data, address = s.recvfrom(MAX)
print ("socket %s received %s bytes from %s" % (s.getsockname(),len(data),address))
s.sendto('Your data was %d bytes' % len(data), address)
#udp_client.py
import socket
MAX = 1024
HOST = '127.0.0.1'
PORT = 1060
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
msg = ('0' * 10).encode('utf-8')
print "==== Using sendto-recvfrom ===="
s.sendto(msg, (HOST, PORT))
data, address = s.recvfrom(MAX)
print 'Client socket name is:', s.getsockname()
print 'Server is: ', address
print 'Server says: ', data
print "==== Using connect + send-recv ===="
s.connect((HOST, PORT))
print 'Client socket name is:', s.getsockname()
print 'Server is: ', s.getpeername()
s.send(msg)
data = s.recv(MAX)
print 'Server says: ', data
UDP broadcast
Udp protocol can deliver broadcast messages to all addresses of a local network.
#udp_server_broadcast.py
import socket
MAX = 1024
ADDR = '' #all local interfaces
PORT = 1060
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((ADDR, PORT))
print (s.getsockname(), "is waiting ...")
while True:
data, address = s.recvfrom(MAX)
print ("socket %s received %s bytes from %s" % (s.getsockname(),len(data),address))
s.sendto('Your data was %d bytes' % len(data), address)
#udp_client_broadcast.py import socket MAX = 1024 HOST = '192.168.0.255' PORT = 1060 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) msg = 'Broadcast message' print "==== Using sendto-recvfrom ====" s.sendto(msg, (HOST, PORT)) data, address = s.recvfrom(MAX) print 'Client socket name is:', s.getsockname() print 'Server is: ', address print 'Server says: ', data
UDP multiplexing (non-blocking)
With non-blocking sockets, we could manage multiple sockets in the same time. Example below includes retry procedure for sending data to server in case of confirmation message is not received (server simulates randim data package loss)
#udp_server_multiplex.py
import select
import socket
import time
import random
MAX = 1024
ADDR = '' #all local interfaces
PORT1 = 1060
PORT2 = 1061
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.setblocking(0)
s1.bind((ADDR, PORT1))
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2.setblocking(0)
s2.bind((ADDR, PORT2))
print (s1.getsockname(), 'and ' , s2.getsockname(), "are waiting ...")
read_list = [s1,s2]
while True:
readable, writable, errored = select.select(read_list, [], [])
for s in readable:
if s == s1:
data, address = s1.recvfrom(MAX)
print ("socket %s received %s bytes from %s" % (s1.getsockname(),len(data),address))
if(random.randint(0, 1)):
s1.sendto('Your data was %d bytes' % len(data), address)
else:
print "Pretending that packet was lost: no response back"
if s == s2:
data, address = s2.recvfrom(MAX)
print ("socket %s received %s bytes from %s" % (s2.getsockname(),len(data),address))
if(random.randint(0, 1)):
s2.sendto('Your data was %d bytes' % len(data), address)
else:
print "Pretending that packet was lost: no response back"
#udp_client_multiplex.py
import socket
import time
MAX = 1024
HOST = '127.0.0.1'
PORT1 = 1060
PORT2 = 1061
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
msg = ('0' * 10).encode('utf-8')
def send1():
print "==== Using sendto-recvfrom ===="
try_nr = 1
delay = 0.1
while True:
print try_nr
try_nr = try_nr + 1
s1.sendto(msg, (HOST, PORT1))
s1.settimeout(delay)
try:
data, address = s1.recvfrom(MAX)
except socket.timeout:
delay *= 2 # wait even longer for the next request
if delay > 2.0:
raise RuntimeError('I think the server is down')
except:
raise # a real error, so we let the user see it
else:
break # we are done, and can stop looping
#s1.sendto(msg, (HOST, PORT1))
#data, address = s1.recvfrom(MAX)
print 'Client socket name is:', s1.getsockname()
print 'Server is: ', address
print 'Server says: ', data
def send2():
print "==== Using connect + send-recv ===="
s2.connect((HOST, PORT2))
print 'Client socket name is:', s2.getsockname()
print 'Server is: ', s2.getpeername()
try_nr = 1
delay = 0.1
while True:
print try_nr
try_nr = try_nr + 1
s2.send(msg)
s2.settimeout(delay)
try:
data = s2.recv(MAX)
except socket.timeout:
delay *= 2 # wait even longer for the next request
if delay > 2.0:
raise RuntimeError('I think the server is down')
except:
raise # a real error, so we let the user see it
else:
break # we are done, and can stop looping
print 'Server says: ', data
while True:
send1()
time.sleep(1)
send2()