Select Git revision
register_test.rs
UDP-client-server.py 8.38 KiB
import socket
import time
import sys
import threading
from threading import Thread
import numpy as np
from array import *
# pymongo for MongoDB support
import pymongo
# For timestamping in MongoDB
import datetime
#pymongo connect
DBConHost = 'localhost'
DBConPort = 27017
DBName = 'matningar'
DBTableName = 'stability'
DBCon = pymongo.MongoClient(DBConHost, DBConPort)
DB = DBCon[DBName]
DBTableStability = DB[DBTableName]
#DEFINE INPUTS HERE
#CLIENT - SENDER
#UDP_DEST_IP = '::1' # IP ADDRESS TO SEND DATAGRAMS TO (v4 or v6)
UDP_DEST_IP = '0.0.0.0' # IP ADDRESS TO SEND DATAGRAMS TO (v4 or v6)
UDP_DEST_PORT = 15005 # IP PORT TO SEND DATAGRAMS TO
PACKET_SIZE = 200 # DATAGRAM SIZE IN BYTES
NR_OF_PACKETS = 100 # TOTAL NR. OF PACKETS TO SEND
PACKETS_PER_SEC = 100 # PACKETS PER SECOND
# CLIENT - RECEIVER
#UDP_RECEIVE_IP = '::1' # LISTENING IP ADDRESS (v6)
UDP_RECEIVE_IP = '0.0.0.0' # LISTENING IP ADDRESS (v4)
UDP_RECEIVE_PORT = 55555 # IP PORT TO LISTEN FOR INCOMING PACKETS
BUFFER = 4096
#CLIENT-RECEIVER PART
def udp_client_receive(UDP_RECEIVE_IP, UDP_RECEIVE_PORT):
ADDR = (UDP_RECEIVE_IP, UDP_RECEIVE_PORT)
#MAKE A DUMB IP VERSION CHECK
if ':' in UDP_RECEIVE_IP:
rcv_sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
else:
rcv_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
global packet_count_rcvd
global cumulative_delay
global min_delay
global max_delay
global rt_delay_array
global jitter
min_delay = 100.
max_delay = 0.
rt_delay_array = array('f')
packet_count_rcvd = 0
cumulative_delay = 0.
jitter = 0.
try:
rcv_sock.bind(ADDR)
print('Server Listening on', ADDR)
except Exception:
print('***ERROR: Server Port Binding Failed')
#FIRE UP THE LISTENER ENGINES
while True:
data, addr = rcv_sock.recvfrom(BUFFER)
data = data.decode("utf-8")
splitdata = data.split(',')
timecount = splitdata[0].strip("('")
rt_delay = (time.time() - float(timecount))
packet_number = str(splitdata[1].strip("' '"))
packet_number = packet_number.lstrip('0')
#WRITE TO FILE AND DO PACKET COUNT
# Useful for debugging and verification purposes
# outfile = open("udp_twoway_results.csv", "a").\
# write(str(time.ctime() + ',' + 'received , ' +
# packet_number + ' , ' + str(rt_delay) + '\n'))
# Store all rt_delay for std.dev. calculation
rt_delay_array.append(rt_delay)
# Comment this line to disable per packet print
#print((time.ctime() + ',' + 'received , ' +
#packet_number + ' , ' + str(rt_delay)))
# Store minimum and maximum delay
if rt_delay > max_delay:
max_delay = rt_delay
if rt_delay < min_delay:
min_delay = rt_delay
packet_count_rcvd = packet_count_rcvd + 1
cumulative_delay = cumulative_delay + rt_delay
outfile.close()
#DATA SUBSCRIPTION (callback)
def cb_event(recipient, threshold):
# TODO
# Somebody call cb_event, identifying themselves with recipient
# defining their threshold value when they want to be notified
# Create list with recipient, threshold
# Run as a separate thread and for example each 5 seconds check if
# any of the thresholds are exceeded. Notify recpient as needed.
print("TODO")
#GET LOCALITY
def get_loc():
# Query locality group, return the bounding box for current loc
#TODO
loc = 0
return loc
#CLIENT SERVER SIDE
def udp_client_send(UDP_DEST_IP, UDP_DEST_PORT,
PACKET_SIZE, NR_OF_PACKETS, PACKETS_PER_SEC):
inter_departure_time = 1. / PACKETS_PER_SEC
packet_count_snd = 0
print("UDP Client Started")
print("UDP target IP:", UDP_DEST_IP)
print("UDP target port:", UDP_DEST_PORT)
print("UDP Packets to Send:", NR_OF_PACKETS)
#IF IPv6
if ':' in UDP_DEST_IP:
if PACKET_SIZE > 97: # BUILD DATAGRAM OF DESIRED SIZE
padding = ''
for j in range(98, PACKET_SIZE):
padding = padding + str(1)
for i in range(1, NR_OF_PACKETS + 1): # SEND SPECIFIED NR OF PKTS
time.sleep(inter_departure_time)
snd_sock6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
snd_sock6.sendto(str(("%.5f" % time.time(), str('%08d' % i),
padding)), (UDP_DEST_IP, UDP_DEST_PORT))
packet_count_snd = packet_count_snd + 1
#IF NOT IPv6
else:
if PACKET_SIZE > 77:
padding = ''
for j in range(78, PACKET_SIZE):
padding = padding + str(1)
for i in range(1, NR_OF_PACKETS + 1):
time.sleep(inter_departure_time)
snd_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
snd_sock.sendto(str(("%.5f" % time.time(), str('%08d' % i),
padding)).encode("utf-8"), (UDP_DEST_IP, UDP_DEST_PORT))
packet_count_snd = packet_count_snd + 1
#WAIT FOR ALL PACKETS TO ARRIVE
packet_wait_time = 3
time.sleep(packet_wait_time)
# Perhaps create a custom object where we store the statistics?
# Or from here save it directly into the database?
PLR = 100 - ((packet_count_rcvd * 100.) / packet_count_snd)
lost = packet_count_snd - packet_count_rcvd
print('\n')
print(packet_count_snd, 'packets sent')
print(packet_count_rcvd, 'packets received')
print(lost, 'Lost packets')
print('packet loss ratio = ', round(PLR, 3), '%\n')
if (max_delay - min_delay != -100):
print('max_delay = ', max_delay)
print('min_delay = ', min_delay)
print('range = ', (max_delay - min_delay))
#CALCULATE THE STANDARD DEVIATION
if rt_delay_array:
print('std.dev = ', np.std(rt_delay_array))
#CALCULATE JITTER
# Clear for a clean slate
jitter = 0
jitter_2 = 0
# Simple version, no weight
for rt0, rt1 in zip(rt_delay_array[:-1], rt_delay_array[1:]):
jitter_2 += np.fabs(rt0 - rt1)
jitter_2 = jitter_2 / (len(rt_delay_array) - 1)
# Version used in RFC 1889, also by iperf
for rt0, rt1 in zip(rt_delay_array[:-1], rt_delay_array[1:]):
jitter += (np.fabs(rt0 - rt1) - jitter) / 16.
print("jitter = ", jitter)
print("jitter = ", jitter_2)
#NETWORK STABILITY BASED ON PACKET LOSS AND DELAY, VALUE 0-100
if packet_count_rcvd == 0:
pass
else:
avg_packet_delay = cumulative_delay / packet_count_rcvd
print('avg.rtt = ', avg_packet_delay)
#CALCULATE STABILITY
# Calculating MOS
# http://en.wikipedia.org/wiki/Mean_opinion_score
#MOS Quality Impairment
#5 Excellent Imperceptible
#4 Good Perceptible but not annoying
#3 Fair Slightly annoying
#2 Poor Annoying
#1 Bad Very annoying
EffectiveLatency = avg_packet_delay + jitter * 2 + 10
if EffectiveLatency < 160:
R = 93.2 - (EffectiveLatency / 40)
else:
R = 93.2 - (EffectiveLatency - 120) / 10
# Now, let's deduct 2.5 R values per percentage of packet loss
R = R - (lost * 2.5)
# Convert the R into an MOS value.(this is a known formula)
mos = 1 + (0.035) * R + (.000007) * R * (R-60) * (100-R)
print("MOS: ", mos)
post = {
#"timestamp" : int(time.time()),
#Not needed since first 4bits of _id is timestamp
"stability" : mos,
"position" : False # Position appended here
}
DBTableStability.insert(post);
#START THE THREADS FOR SENDER AND RECEIVER
if __name__ == "__main__":
receiver_thread = Thread(target=udp_client_receive,
args=(UDP_RECEIVE_IP, UDP_RECEIVE_PORT))
receiver_thread.daemon = True
receiver_thread.start()
time.sleep(1)
while threading.activeCount() <= 2:
# Set the count of the received packets to 0,
# since the listener thread runs continously
packet_count_rcvd = 0
packet_count_snd = 0
sender_thread = Thread(target=udp_client_send,
args=(UDP_DEST_IP, UDP_DEST_PORT,
PACKET_SIZE, NR_OF_PACKETS,
PACKETS_PER_SEC))
sender_thread.start()
while sender_thread.is_alive():
time.sleep(1)
# Measurement done, store data and then move on
# While testing, end after one iteration
sys.exit()